﻿using System;
using System.Collections;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using GMap.NET;
using GMap.NET.WindowsPresentation;
using InteractiveMapApp.CustomMarkers;
using System.Messaging;
using System.Runtime.InteropServices;
using System.Windows.Documents;
using Growl.Connector;
using System.Text;
using System.Diagnostics;
using System.IO;

namespace InteractiveMapApp
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        //projector app stuff
        public bool projectorMode = Properties.Settings.Default.ProjectorMode;
        bool thereIsNewStoryWaitingToBeAdded = false;
        Story messageReceiveStory;


        #region auckland position
        static PointLatLng mapCenterPosition = new PointLatLng(Properties.Settings.Default.mapCenterLattitude, Properties.Settings.Default.mapCenterLongitude);
        PointLatLng cityBoundTopLeft;
        PointLatLng previousPosition = new PointLatLng(-36.866667, 174.766667);
        public static PointLatLng currentPosition = new PointLatLng(-36.866667, 174.766667);
        RectLatLng theCityBoundary;
        RectLatLng validStoryBoundary;///to determine where stories should be allowed to be placed
        double auckTopLat;
        double auckBottomLat;
        double auckLeft;
        double auckRight;
        #endregion

        public bool aucklandCircleZoneIsBeingDraggedOver = false;
        const int SQUARE_Z_INDEX = -1;
        int currentStoryType;
        int currentTimeSlotType;
        string machineName = "TouchApp";//System.Environment.MachineName;

        #region TIMER CITY
        //specific timers for projector
        System.Windows.Forms.Timer pushNewStoryTimer;
        public System.Windows.Forms.Timer showStoryBubbleTimer;
        System.Windows.Forms.Timer manageAnimTimer;

        public System.Windows.Forms.Timer idleTimer = new System.Windows.Forms.Timer();
        System.Windows.Forms.Timer zoomTimer = new System.Windows.Forms.Timer();
        System.Timers.Timer myStoryLifetime = new System.Timers.Timer();
        System.Timers.Timer fetchRecentStoriesTimer = new System.Timers.Timer();
        System.Windows.Forms.Timer touchLeaveTimeout = new System.Windows.Forms.Timer();
        int idleTimerRunCount = 0;
        int howManyTimesCanIdleTimerRunConsequentlyBeforeResetAppToDefaultState = 10;
        #endregion

        /// <summary>
        /// Available Categories
        /// * Store objects of Category class
        /// * This is initialized upon application startup period and 
        /// never modified again. If there is a change to Categories in the DB, it will take effect
        /// after application restart.
        /// </summary>
        ArrayList categoriesArrayList = new ArrayList();
        /// <summary>
        /// Available TimeSlots
        /// * Store objects of TimeSlot class
        /// * This is initialized upon application startup period and 
        /// never modified again. If there is a change to TimeSlot in the DB, it will take effect
        /// after application restart.
        /// </summary>
        ArrayList timeSlotArrayList = new ArrayList();
        /// <summary>
        /// Storing stories made from this user 
        /// * Store objects of Story class
        /// * Expires after a while -> stories removed from here and sent to storiesArrayList based on timer
        /// * Added to everytime the user creates a story
        /// </summary>
        ArrayList myStoriesArrayList = new ArrayList();

        StoriesHelperClass storyManager;

        //private const string queueName = @".\Private$\group26";
        private string queueName = "FormatName:DIRECT=OS:" + Properties.Settings.Default.messageQueueHostName + @"\private$\" + Properties.Settings.Default.messageQueueName;
        //private string queueName = "FormatName:DIRECT=OS:" + "AmritUni-PC" + @"\private$\group26";
        MessageQueue queue = null;

        int MaxNumberMyStoriesToShowAtATime = Properties.Settings.Default.MaxNumberMyStoriesToShowAtATime;
        int MaxNumberMuseumStoriesToShowAtATime = Properties.Settings.Default.MaxNumberMuseumStoriesToShowAtATime;
        int MaxNumberRandomStoriesToShowAtATime = Properties.Settings.Default.MaxNumberRandomStoriesToShowAtATime;
        //int MaxNumberTotalStoriesToShowAtATime;

        string RequestPageURL = Properties.Settings.Default.RequestPageURL;
        int storyCycleInterval = Properties.Settings.Default.storyCycleInterval;
        int UserStoryLifetime = Properties.Settings.Default.UserStoryLifetime;
        int fetchRecentStoriesInterval = Properties.Settings.Default.fetchRecentStoriesInterval;
        public static string iconsStarterPath = Properties.Settings.Default.iconsPathStarterURL;
        public bool portraitScreen = Properties.Settings.Default.OrientationPortrait;

        object previousCategorySender;
        object previousTimeSlotSender;
        bool aCategoryHasBeenSelected = false;
        bool aTimeSlotHasBeenSelected = false;
        ArrayList prevTimeSlotArrayList;//to store the showFilter states of the buttons
        ArrayList prevCategoriesArrayList;//in the case that we want to reset/cancel the operation
        bool isFilterTouchDown = false;  //different from mouse down because this is with a timer too
        bool mouseDown = false; // for filter buttons to determine if there is an active press when the mouse/touch moves off the element 
        bool areButtonsBeingUsed = true; // for zoom and help buttons to overcome 'stuck' buttons 
        bool shouldReloadOnTouch = true; //defines when program should interpret a touch/tap/click as an indication to reload stories
        bool mapScrolled = false;
        public bool readMode = false;
        bool isFilterAnimationRunning = false;
        bool storyJustSubmitted = false;
        bool termsNestedInHelpCanvas = false;
        bool errorOnLoad = false;

        public bool userIsCurrentlyReadingAStory = false;
        public bool touchedMarker = false;  //if this touch is not done on a marker

        DoubleAnimation scale; //for the filter brush over animation
        Storyboard panMapStoryBoard;

        #region set up error message constants etc. for Growl Notification System
        private GrowlConnector growl;
        private Growl.Connector.Application application;
        NotificationType newNotification = new NotificationType("Interactive Map App", "Interactive Map App");

        NotificationType newStoryNotification = new NotificationType("Interactive Map App", "New Story: Success", Properties.Resources.button_story_up, true);
        private const string newStorySuccessTitle = "Success";
        private const string newStorySuccessNotification = "Your memory has been shared";

        NotificationType errorNotification = new NotificationType("Interactive Map App", "Error", Properties.Resources.button_story_down, true);
        private const string storyCreationFailedToDragTheIconTitle = "Please try again";
        private const string storyCreationFailedToDragTheIconNotification = "Drag and drop the new story icon to start sharing your memory";
        private const string internetProblemTitle = "Internet Error";
        private const string internetProblemNotification = "Due to an Internet error, this story has not been added. We apologise for the inconvenience.";
        private const string storyInputCancelledTitle = "Cancelled";
        private const string storyInputCancelledNotification = "Memory input cancelled.";

        NotificationType filterApplied = new NotificationType("Interactive Map App", "Filter applied", Properties.Resources.button_story_down, true);
        private const string filterAppliedTitle = "Filters Applied";
        private const string filtersAppliedNotification = "Your chosen filters have been applied";

        private const string filterStatusResetTitle = "Filters Reset";
        private const string filterStatusResetNotification = "The filters status has been reset.";

        NotificationType newStoryValidation = new NotificationType("Interactive Map App", "New Story : Validation", Properties.Resources.button_story_down, true);
        private const string newStoryValidationTitle = "Incomplete memory";
        private const string newStoryCategoryNotSelectedNotification = "Please select the category which best suits your memory.";
        private const string newStoryTimeNotSelectedNotification = "Please select the time frame to which your memory belongs.";
        private const string newStoryTextNotTypedNotification = "Please enter the description of your memory.";
        private const string updatedWithNewStoriesTitle = "New memories updated";
        private const string updatedWithNewStoriesNotification = "New memories have been downloaded";

        #endregion

        const char stringSplitChar = '\'';

        public MainWindow()
        {
            InitializeComponent();

            if (projectorMode)
            {
                Console.WriteLine("This application is configured for Projector Mode");

                MaxNumberRandomStoriesToShowAtATime = 0;//we don't want random stories on this screen.

                pushNewStoryTimer = new System.Windows.Forms.Timer();
                showStoryBubbleTimer = new System.Windows.Forms.Timer();
                manageAnimTimer = new System.Windows.Forms.Timer();

                //remove all from display except for mainmap
                for (int i = 0; i < grid.Children.Count; i++)
                {
                    if (!(grid.Children[i] is GMapControl))
                    {
                        //remove all except the black masking rectangle
                        if (!(grid.Children[i] is System.Windows.Shapes.Rectangle))
                        {
                            grid.Children.RemoveAt(i);
                            i--;
                        }
                            //if it is a rectangle check if it is a black masking one
                        else if (!(grid.Children[i] as System.Windows.Shapes.Rectangle).Name.Equals("blackRectangle1") && !(grid.Children[i] as System.Windows.Shapes.Rectangle).Name.Equals("blackRectangle2") && !(grid.Children[i] as System.Windows.Shapes.Rectangle).Name.Equals("blackRectangle3") && !(grid.Children[i] as System.Windows.Shapes.Rectangle).Name.Equals("blackRectangle4"))
                        {
                            grid.Children.RemoveAt(i);
                            i--;
                        }
                    }
                }
            }

            else //normal touch mode
            {
                Console.WriteLine("This application is configured to operate in Touch Screen Mode");
                scale = new DoubleAnimation();
               
                
                #region // map events
                //MainMap.OnCurrentPositionChanged += new CurrentPositionChanged(MainMap_OnCurrentPositionChanged);
                //MainMap.OnTileLoadComplete += new TileLoadComplete(MainMap_OnTileLoadComplete);
                //MainMap.OnTileLoadStart += new TileLoadStart(MainMap_OnTileLoadStart);
                //MainMap.OnMapTypeChanged += new MapTypeChanged(MainMap_OnMapTypeChanged);
                //MainMap.MouseMove += new System.Windows.Input.MouseEventHandler(MainMap_MouseMove);
                //MainMap.Loaded += new RoutedEventHandler(MainMap_Loaded);
                //MainMap.MouseEnter += new MouseEventHandler(MainMap_MouseEnter);
                //MainMap.MouseRightButtonUp += new MouseButtonEventHandler(MainMap_MouseRightButtonUp);
                //MainMap.MouseLeftButtonDown += new System.Windows.Input.MouseButtonEventHandler(MainMap_MouseLeftButtonDown);
                //MainMap.MouseWheel +=new MouseWheelEventHandler(MainMap_MouseWheel);
                MainMap.OnMapZoomChanged += new MapZoomChanged(MainMap_OnMapZoomChanged);
                MainMap.OnCurrentPositionChanged += new CurrentPositionChanged(MainMap_OnCurrentPositionChanged);
                #endregion
            }

            if (portraitScreen)
            {
                Console.WriteLine("This screen is operating in Portrait mode");
                window.Width = Properties.Settings.Default.YSize;
                window.Height = Properties.Settings.Default.XSize;
            }
            else
            {
                Console.WriteLine("This screen is operating in Landscape mode");
                window.Width = Properties.Settings.Default.XSize;
                window.Height = Properties.Settings.Default.YSize;
            }
            grid.Height = window.Height;
            grid.Width = window.Width;
            MainMap.Height = window.Height;
            MainMap.Width = window.Width;
        }


        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            //re-position the window since the centre screen startup location includes the 
            //task bar so the actual centre is off
            window.Top = 0;
            window.Left = 0;
            // config map
            //MainMap.MapType = MapType.NearMap;
            MainMap.MapType = MapType.OpenStreetMap;
            MainMap.ShowCenter = false; //hide the crosshair
            MainMap.AllowDrop = true;
            MainMap.MaxZoom = Properties.Settings.Default.MapMaxZoom;
            MainMap.MinZoom = Properties.Settings.Default.MapMinZoom;
            MainMap.Zoom = Properties.Settings.Default.MapDefaultZoom;
            MainMap.Position = mapCenterPosition;
            MainMap.IgnoreMarkerOnMouseWheel = true;
            //restrict user from leaving the bounds of auckland            
            cityBoundTopLeft = new PointLatLng(Properties.Settings.Default.cityBoundTopLeftLattitude, Properties.Settings.Default.cityBoundTopLeftLongitude);
            PointLatLng cityBoundBottomRight = new PointLatLng(Properties.Settings.Default.cityBoundBottomRightLattitude, Properties.Settings.Default.cityBoundBottomRightLongitude);
            auckTopLat = cityBoundTopLeft.Lat;
            auckBottomLat = cityBoundBottomRight.Lat;
            auckLeft = cityBoundTopLeft.Lng;
            auckRight = cityBoundBottomRight.Lng;
            //MaxNumberTotalStoriesToShowAtATime = MaxNumberRandomStoriesToShowAtATime + 
            //    MaxNumberMuseumStoriesToShowAtATime + 
            //    MaxNumberRecentStoriesToShowAtATime + 
            //    MaxNumberMyStoriesToShowAtATime;
            SizeLatLng auckSize = new SizeLatLng((auckTopLat - auckBottomLat), (auckRight - auckLeft));
            theCityBoundary = new RectLatLng(cityBoundTopLeft, auckSize);
            //MainMap.BoundsOfMap = new RectLatLng?(new RectLatLng(cityBoundTopLeft, auckSize));


            SizeLatLng validStorySize = new SizeLatLng(((-36.025025966794715) - (-37.26112521328509)), (175.55354118347213 - 174.15458679199264));
            PointLatLng validStoryBoundTopLeft = new PointLatLng(-36.025025966794715, 174.15458679199264);
            validStoryBoundary = new RectLatLng(validStoryBoundTopLeft, validStorySize);



            MainMap.CacheLocation = AppDomain.CurrentDomain.BaseDirectory; //bin/debug folder
            MainMap.Manager.Mode = AccessMode.ServerAndCache;

            ////Used for limiting user from 'pinch zooming' out too far out of the area
            //double scrollBoundTopLat = Properties.Settings.Default.scrollBoundTopLat;
            //double scrollBoundLeftLng = Properties.Settings.Default.scrollBoundLeftLng;
            //double scrollBoundBottomLat = Properties.Settings.Default.scrollBoundBottomLat;
            //double scrollBoundRightLng = Properties.Settings.Default.scrollBoundRightLng;
            //auckBoundRect = new RectLatLng(scrollBoundTopLat, scrollBoundLeftLng, (scrollBoundRightLng - scrollBoundLeftLng), (scrollBoundTopLat - scrollBoundBottomLat));

            if (!projectorMode)//touch
            {
                if ((MainMap.Height < 1000) || portraitScreen && MainMap.Width < 1000)//if vertical size is small then make the keyboard fit
                {
                    floatingTouchScreenKeyboard1.Height = 340;
                }
                if (floatingTouchScreenKeyboard1.Width > MainMap.Width)//make keyboard width fit if screen width is too low
                {
                    floatingTouchScreenKeyboard1.Width = MainMap.Width;
                }

                floatingTouchScreenKeyboard1.VerticalOffset = MainMap.Height - floatingTouchScreenKeyboard1.Height - 300;
                floatingTouchScreenKeyboard1.HorizontalOffset = 0;
                

                if ((MainMap.Width >= 1680 && MainMap.Width < 1920) || portraitScreen && (MainMap.Height < 1680 && MainMap.Height < 1920))
                {
                    //make elements bigger for high res
                    bubble_youarehere.Height = bubble_youarehere.Height * 1.3;
                    bubble_explain.Height = bubble_explain.Height * 1.3;

                    bubble_youarehere.Width = bubble_youarehere.Width * 1.3;
                    bubble_explain.Width = bubble_explain.Width * 1.3;

                }
                else if (MainMap.Width >= 1920 || portraitScreen && MainMap.Height >= 1920)
                {
                    //make elements bigger for high res
                    bubble_youarehere.Height = bubble_youarehere.Height * 1.5;
                    bubble_explain.Height = bubble_explain.Height * 1.5;

                    bubble_youarehere.Width = bubble_youarehere.Width * 1.5;
                    bubble_explain.Width = bubble_explain.Width * 1.5;
                }

                //the filter brush over animation
                scale.Duration = new Duration(new TimeSpan(0, 0, 0, 0, 100));
            }
            else//projector
            {
                MainMap.CanDragMap = true;

                pushNewStoryTimer.Interval = 50;
                pushNewStoryTimer.Tick += new EventHandler(pushNewStoryTimer_Tick);
                pushNewStoryTimer.Start();

                showStoryBubbleTimer.Interval = 20000; //20 seconds for now
                showStoryBubbleTimer.Tick += new EventHandler(showStoryBubbleTimer_Tick);
                showStoryBubbleTimer.Start();

                manageAnimTimer.Interval = 10000;
                manageAnimTimer.Tick += new EventHandler(manageAnimTimer_Tick);
                manageAnimTimer.Start();

                if (MainMap.Height == 1440 && MainMap.Width == 900) 
                {
                    //blackRectangle1.Visibility = Visibility.Visible;
                    //blackRectangle2.Visibility = Visibility.Visible;
                    //blackRectangle3.Visibility = Visibility.Visible;
                    //blackRectangle4.Visibility = Visibility.Visible;
                }
            }

            MainMap.DragButton = MouseButton.Right;
            MainMap.CanDragMap = true;

            //Cursor = Cursors.Wait;
            Console.WriteLine("Application Launched : " + DateTime.Now);

            storyManager = new StoriesHelperClass();

            if (storyManager.SetUpDB(projectorMode))
            {
                categoriesArrayList.AddRange(storyManager.GetCategoriesArrayList());
                timeSlotArrayList.AddRange(storyManager.GetTimeSlotsArrayList());

                initialiseMarkerIconsWithTags();
                initialiseTimeSlotIconsWithTags();

                //get random set of stories which exist for this current view area & add to map
                ReloadStories(false);

                idleTimer.Interval = storyCycleInterval;
                idleTimer.Tick += new EventHandler(idleTimer_Tick);
                idleTimer.Start();//to redo events after # time elapse
                idleTimerRunCount = 0;

                fetchRecentStoriesTimer.Elapsed += new System.Timers.ElapsedEventHandler(fetchRecentStoriesTimer_Elapsed);
                fetchRecentStoriesTimer.Interval = fetchRecentStoriesInterval;
                fetchRecentStoriesTimer.Start();

                System.Timers.Timer obseleteStoryCheck = new System.Timers.Timer();
                obseleteStoryCheck.Elapsed += new System.Timers.ElapsedEventHandler(obseleteStoryCheck_Elapsed);
                obseleteStoryCheck.Interval = 180000;  //180 seconds then check for updates
                obseleteStoryCheck.Start();

                if (CreateQueue())//prepares message queue
                {
                    //removeMessages();//uncomment if you want to purge all messages in the queue
                }

                if (!projectorMode)//touch
                {

                    ///init the welcome screen
                    displayWelcomeScreen();
                }

                //register the growl application
                if (GrowlConnector.IsGrowlRunningLocally())
                {
                    this.growl = new GrowlConnector();
                    this.growl.EncryptionAlgorithm = Cryptography.SymmetricAlgorithmType.PlainText;
                    this.application = new Growl.Connector.Application("Ahi Kaa Map");

                    this.application.Icon = Properties.Resources.lightGreenTrees;
                    this.growl.Register(application, new NotificationType[] { newNotification });
                }
            }

            else
            {
                //TODO : Instead of this, launch the app but
                //have a popup window or something
                //which shows this message (less ugly)

                /*
                * if false was returned by setUpDB() that means something is really badly wrong!
                * So.. we cannot proceed, what to do? Show meaningful message
                */
                Console.WriteLine("Fatal Error : Local Database Problem");
                MessageBox.Show("Fatal Error : There was a problem starting the application. \n" +
                        "Please report this to the System Administrator.");
                errorOnLoad = true;
            }

            /*
             * This section needs to be down here so that the panTo doesn't
             * throw an error incase SetUpDB failed
             */
            panMapStoryBoard = (Storyboard)Resources["panMapStoryBoard"];
            //Cursor = Cursors.Arrow;

        }

        void obseleteStoryCheck_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (sender != null)
            {
                (sender as System.Timers.Timer).Stop();

                storyManager.CheckForObseleteStories();  //make request to server for stories that should be deleted

                (sender as System.Timers.Timer).Start();
            }
        }
        



        /// <summary>
        /// Displays the welcome screen.  Here we will cycle between 2 screens
        /// The map will pan underneath 
        /// </summary>
        //bool initialWelcomeScreen = true;
        bool welcomeActive = false;
        //System.Windows.Forms.Timer welcomePanTimer;
        //System.Windows.Forms.Timer welcomeSwitchTimer;
        //PointLatLng[] welcomePanPoints = new PointLatLng[11] { new PointLatLng(-36.8606267, 174.7778184),
        //    new PointLatLng(-36.9309840, 174.5376426), new PointLatLng(-36.7710936, 174.7293884),
        //    new PointLatLng(-36.9999740, 174.9056846), new PointLatLng(-36.8480242, 174.7615749),
        //    new PointLatLng(-36.8636139, 174.6146328), new PointLatLng(-36.4024170, 174.6458751),
        //    new PointLatLng(-36.6644864, 174.4288952), new PointLatLng(-36.1998806, 175.4293377), 
        //    new PointLatLng(-36.7859429, 174.8632843) , mapCenterPosition };

        /// <summary>
        /// Displays the white-faded map with normal ui elements removed.
        /// This default screen welcomes users with some initial info
        /// and the option to add or read stories.
        /// </summary>
        private void displayWelcomeScreen()
        {
            welcomeActive = true;
            storyJustSubmitted = false;

            //hide other UI elements
            stackPanel1.Visibility = Visibility.Hidden; //zoom controls
            helpBtn.Visibility = Visibility.Hidden;
            readModeBtn.Visibility = Visibility.Hidden;
            writeModeBtn.Visibility = Visibility.Hidden;
            homeBtn.Visibility = Visibility.Hidden;
            addStoryMarker.Visibility = Visibility.Hidden;
            //label1.Visibility = Visibility.Hidden;
            showFilterPanelImgBtn.Visibility = Visibility.Hidden;
            showButtonRect.Visibility = Visibility.Hidden;
            filterCanvas.Visibility = Visibility.Hidden;
            bubble_draganddropme.Visibility = Visibility.Hidden;
            userIsCurrentlyReadingAStory = false;


            //remove user story tag from previous user stories
            ReloadStories(true);
            if (myStoryLifetime != null)
            {
                myStoryLifetime.Stop();
                myStoryLifetime.Elapsed -= new System.Timers.ElapsedEventHandler(myStoryLifetime_Elapsed);
            }
            //adds the old users stories into the main list before wiping it
            if (myStoriesArrayList.Count > 0)
            {
                storyManager.InsertUsersNewStoriesIntoDB(myStoriesArrayList);
                myStoriesArrayList = null;
                myStoriesArrayList = new ArrayList();
            }
            MainMap.Markers.Clear();




            if (whiteRectangleCanvas.Visibility == System.Windows.Visibility.Hidden)
            {
                whiteRectangleCanvas.Visibility = System.Windows.Visibility.Visible;
                whiteRectangleCanvas.Opacity = 0;
                whiteRectangleCanvas.Height = window.Height;
                whiteRectangleCanvas.Width = window.Width;
                Storyboard fadeInRect = (Storyboard)Resources["whiteRectCanvasFadeIn"];
                fadeInRect.Begin();
            }

            ////decides which welcome elements to show
            //if (initialWelcomeScreen)
            //{
            //    //---hide alternate elements//
            //    bubble_explain.Visibility = Visibility.Hidden;
            //    button_addstory.Visibility = Visibility.Hidden;
            //    button_readstory.Visibility = Visibility.Hidden;
            //    //label_or.Visibility = Visibility.Hidden;
            //    //label_whatwouldyouliketodo.Visibility = Visibility.Hidden;

            //    //---set position of elements//
            //    if (window.Width >= 1680)
            //    {
            //        bubble_haeremai.Margin = new Thickness(160, 80, 0, 0);
            //        button_start.Margin = new Thickness(0, 0, 220, 0);
            //    }
            //    else
            //    {
            //        bubble_haeremai.Margin = new Thickness(60, 80, 0, 0);
            //    }
                
            //    bubble_youarehere.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
            //    bubble_youarehere.Margin = new Thickness(0, 68, 180, 210);

            //    //---show these ones//
            //    button_start.Visibility = Visibility.Visible;
            //    bubble_haeremai.Visibility = Visibility.Visible;
            //    bubble_youarehere.Visibility = Visibility.Visible;

            //    //code to pan around
            //    //probably stick a few constants of LatLng points and pan between them.
            //    // really nice would be to pan to different AM stories and show them.. but we have no real AM stories

            //    if (welcomePanTimer == null)
            //    {
            //        welcomePanTimer = new System.Windows.Forms.Timer();
            //        welcomePanTimer.Tick += new EventHandler(welcomePanTimer_Tick);
            //        welcomePanTimer.Interval = 4000; //four seconds between each pan
            //        welcomePanTimer.Start();
            //        ReloadStories(true);
            //    }
            //    else
            //    {
            //        welcomePanTimer.Start();
            //        ReloadStories(true);
            //    }
            //}
            //else
            //{
                //---hide alternate elements//
                button_start.Visibility = Visibility.Hidden;


                bubble_youarehere.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
                bubble_youarehere.Margin = new Thickness((window.Width / 2) - (bubble_youarehere.Width / 2), 70, 0, 20);

                //----show these ones//
                bubble_explain.Visibility = Visibility.Visible;
                bubble_youarehere.Visibility = Visibility.Visible;
                button_addstory.Visibility = Visibility.Visible;
                button_readstory.Visibility = Visibility.Visible;
                button_addstory.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_addstory.png", UriKind.Relative));

                //Storyboard StopBtnAnim = (Storyboard)Resources["stopStoryBtnStoryboard"];
                //StopBtnAnim.Begin();

                //Storyboard BtnAnim = (Storyboard)Resources["storyBtnStoryboard"];
                //BtnAnim.Begin();

                //if (welcomePanTimer != null)
                //{
                //    welcomePanTimer.Stop();
                //}
                MainMap.Markers.Clear(); //hide markers
                idleTimer.Stop();
            //}
            //initialWelcomeScreen = !initialWelcomeScreen; //reverses the welcome elements next time.


            //if (welcomeSwitchTimer == null)
            //{
            //    welcomeSwitchTimer = new System.Windows.Forms.Timer();
            //    welcomeSwitchTimer.Tick += new EventHandler(welcomeSwitchTimer_Tick);
            //    welcomeSwitchTimer.Interval = 30000; //thirty seconds between each welcome screen
            //    welcomeSwitchTimer.Start();
            //}
            //else
            //{
            //    welcomeSwitchTimer.Stop();
            //    welcomeSwitchTimer.Start();
            //}
        }

        ///// <summary>
        ///// every 30 seconds the welcome screen will change to the alternate one
        ///// </summary>
        ///// <param name="sender"></param>
        ///// <param name="e"></param>
        //void welcomeSwitchTimer_Tick(object sender, EventArgs e)
        //{
        //    displayWelcomeScreen();
        //}

        ///// <summary>
        ///// timer to decide when to pan to the welcome screen pan points
        ///// </summary>
        ///// <param name="sender"></param>
        ///// <param name="e"></param>
        //void welcomePanTimer_Tick(object sender, EventArgs e)
        //{
        //    welcomePanTimer.Stop();

        //    Random random = new Random();
        //    int index = random.Next(welcomePanPoints.Length);
        //    panTo(welcomePanPoints[index], false, 1);
        //    ReloadStories(true);

        //    welcomePanTimer.Start();
        //}

        /// <summary>
        /// cleans up for the welcome screen finishing
        /// reshows all the normal elements for operation
        /// </summary>
        private void closeWelcomeScreen()
        {
            welcomeActive = false;

            //if (welcomePanTimer != null)
            //{
            //    welcomePanTimer.Tick -= new EventHandler(welcomePanTimer_Tick);
            //    welcomePanTimer.Stop();
            //    welcomePanTimer = null;
            //}
            //if (welcomeSwitchTimer != null)
            //{
            //    welcomeSwitchTimer.Tick -= new EventHandler(welcomeSwitchTimer_Tick);
            //    welcomeSwitchTimer.Stop();
            //    welcomeSwitchTimer = null;
            //}

            //Storyboard StopBtnAnim = (Storyboard)Resources["stopStoryBtnStoryboard"];
            //StopBtnAnim.Begin();

            Storyboard rectfadeOut = (Storyboard)Resources["whiteRectCanvasFadeOut"];
            rectfadeOut.Begin();

            //show other UI elements
            stackPanel1.Visibility = Visibility.Visible;//zoom controls
            helpBtn.Visibility = Visibility.Visible;
            //label1.Visibility = Visibility.Visible;

            //hide welcome elements
            button_start.Visibility = Visibility.Hidden;
            button_addstory.Visibility = Visibility.Hidden;
            button_readstory.Visibility = Visibility.Hidden;
            bubble_youarehere.Visibility = Visibility.Hidden;
            bubble_explain.Visibility = Visibility.Hidden;
            //label_or.Visibility = Visibility.Hidden;
            //label_whatwouldyouliketodo.Visibility = Visibility.Hidden;

            idleTimer.Start();
            panTo(mapCenterPosition, true, 0);
        }

        /// <summary>
        /// Switches to the read story mode.
        /// Moves, removes and adds appropriates elements
        /// </summary>
        private void ReadStoryMode()
        {
            //hide add story marker
            //hide the drag drop assistance bubble
            //show the filter panel
            //hide the switch to read mode button
            //show the switch to write mode button
            //enable read story function (tap on story)
            //show markers on the map

            readMode = true;
            //show the most recent user story after story entry -- if any
            bool markerShown = false;
            foreach (GMapMarker gm in MainMap.Markers)
            {
                if ((gm.Shape as CustomMarker).showThisBubbleWhenCreating)
                {
                    (gm.Shape as CustomMarker).ShowMarkerBubble();
                    markerShown = true;
                    break;
                }
            }

            if (!markerShown)
            {
                ReloadStories(true);
            }

            //hide other UI elements
            //newStoryButtonDown.Visibility = Visibility.Hidden;
            //newStoryButton.Visibility = Visibility.Hidden;
            readModeBtn.Visibility = Visibility.Hidden;
            addStoryMarker.Visibility = Visibility.Hidden;
            bubble_draganddropme.Visibility = Visibility.Hidden;

            //show needed elements
            stackPanel1.Visibility = Visibility.Visible;//zoom controls
            helpBtn.Visibility = Visibility.Visible;
            //label1.Visibility = Visibility.Visible;
            writeModeBtn.Visibility = Visibility.Visible;
            homeBtn.Visibility = Visibility.Visible;

            if (!isFilterAnimationRunning  && filterCanvas.Visibility == Visibility.Hidden) //disable until animation is done
            {
                ShowFilterCanvas();
            }
        }

        /// <summary>
        /// Switches to the write story mode.
        /// Moves, removes and adds appropriates elements
        /// </summary>
        private void WriteStoryMode()
        {
            if (!isFilterAnimationRunning) //disable until animation is done
            {
                //show add story marker
                //show the drag drop assistance bubble (until first move of marker)
                //hide the filter panel
                //show the switch to read mode button
                //hide the switch to write mode button
                //disable read story function (tap on story)
                //hide markers on the map (disable idle timer reload function)

                MainMap.Markers.Clear(); //hide markers

                readMode = false;

                //hide other UI elements
                writeModeBtn.Visibility = Visibility.Hidden;
                showFilterPanelImgBtn.Visibility = Visibility.Hidden;
                showButtonRect.Visibility = Visibility.Hidden;
                HideFilterCanvas();


                //show other UI elements
                stackPanel1.Visibility = Visibility.Visible;//zoom controls
                helpBtn.Visibility = Visibility.Visible;
                //label1.Visibility = Visibility.Visible;
                readModeBtn.Visibility = Visibility.Visible;
                addStoryMarker.Visibility = Visibility.Visible;
                bubble_draganddropme.Visibility = Visibility.Visible;
                homeBtn.Visibility = Visibility.Visible;


                //resets the addStoryMarker position to default pos
                addStoryMarker.VerticalAlignment = System.Windows.VerticalAlignment.Bottom;
                addStoryMarker.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
                addStoryMarker.Margin = new Thickness(20, 0, 0, 100); //go back to default


                Storyboard animMarker = (Storyboard)Resources["addStoryMarkerStoryboard"];
                animMarker.Begin();
            }
        }

        ///// <summary>
        ///// Shows the Thank you for sharing your Auckland story
        ///// message with the options of choosing to read or write more stories
        ///// </summary>
        //private void ShowStorySubmittedScreen()
        //{
        //    //show label with the Thankyou text
        //    label_thankyouforsharing.Visibility = Visibility.Visible;
        //    label_thankyouforsharing2.Visibility = Visibility.Visible;
        //    //show the read story button
        //    button_readstory.Visibility = Visibility.Visible;
        //    //show the write another story button
        //    button_addstory.Visibility = Visibility.Visible;
        //    button_addstory.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_addanotherstory.png", UriKind.Relative));


        //    //hide other UI elements
        //    stackPanel1.Visibility = Visibility.Hidden; //zoom controls
        //    helpBtn.Visibility = Visibility.Hidden;
        //    readModeBtn.Visibility = Visibility.Hidden;
        //    label1.Visibility = Visibility.Hidden;
        //}

        /// <summary>
        /// Shows the dialogue to confirm the dragged marker position
        /// to input a new story
        /// </summary>
        private void ShowConfirmPositionCanvas()
        {
            //make the faded background visible
            blackRectangleCanvas.Visibility = Visibility.Visible;
            blackRectangleCanvas.Opacity = 0;
            blackRectangleCanvas.Height = window.Height;
            blackRectangleCanvas.Width = window.Width;
            Storyboard fadeInRect = (Storyboard)Resources["blackRectCanvasLightFadeIn"];
            fadeInRect.Begin();


            //fade in confirmPositionCanvas 
            confirmPositionCanvas.Visibility = Visibility.Visible;
            confirmPositionCanvas.Opacity = 0;
            Storyboard fadeOut = (Storyboard)Resources["ConfirmCanvasFadeIn"];
            fadeOut.Begin();
        }

        /// <summary>
        /// Hides the dialogue which confirms the dragged marker position
        /// </summary>
        private void HideConfirmPositionCanvas()
        {
            Storyboard fadeOut = (Storyboard)Resources["ConfirmCanvasFadeOut"];
            fadeOut.Begin();
        }

        /// <summary>
        /// Shows the read story bubble
        /// </summary>
        public void ShowReadStoryCanvas()
        {
            //make the faded background visible
            blackRectangleCanvas.Visibility = Visibility.Visible;
            blackRectangleCanvas.Opacity = 0;
            blackRectangleCanvas.Height = window.Height;
            blackRectangleCanvas.Width = window.Width;
            Storyboard fadeInRect = (Storyboard)Resources["blackRectCanvasLightFadeIn"];
            fadeInRect.Begin();


            //fade in confirmPositionCanvas 
            readStoryCanvas.Visibility = Visibility.Visible;
            Storyboard showStory = (Storyboard)Resources["showReadCanvasStoryboard"];
            showStory.Begin();

            report_text.IsEnabled = true;
            report_text.Opacity = 1;

            //foreach (GMapMarker gmark in MainMap.Markers)
            //{
            //    if ((gmark.Shape as CustomMarker).thisMarkersPopupIsShowing && (gmark.Shape as CustomMarker).reported)
            //    {
            //        //content
            //        readStoryTextBlock.Text = "You have reported this story.\nThank you for helping us keep our stories safe.";
            //        readStoryTextBlock.FontSize = 28;
            //        readStoryTextBlock.TextDecorations.Add(TextDecorations.Underline);
            //        readStoryTextBlock.Foreground = new SolidColorBrush(Color.FromArgb((byte)0xFF, (byte)0x40, (byte)0x81, (byte)0x9B));
            //        readStoryTextBlock.TextAlignment = TextAlignment.Center;

            //        //title
            //        readStoryTitleTextBlock.FontSize = 28;
            //        readStoryTitleTextBlock.TextDecorations.Add(TextDecorations.Underline);
            //        readStoryTitleTextBlock.Foreground = new SolidColorBrush(Color.FromArgb((byte)0xFF, (byte)0x40, (byte)0x81, (byte)0x9B));
            //        readStoryTitleTextBlock.TextAlignment = TextAlignment.Center;
            //        readStoryTitleTextBlock.Text = "STORY REPORTED";

            //        button_report.IsEnabled = false;
            //        button_report.Opacity = 0.2;
            //        button_report.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_report_pressed.png", UriKind.Relative));
            //    }
            //}
        }

        /// <summary>
        /// Hides the read story bubble
        /// </summary>
        public void HideReadStoryCanvas()
        {
            if (readStoryCanvas.Visibility == Visibility.Visible)
            {
                Storyboard hideStory = (Storyboard)Resources["hideReadCanvasStoryboard"];
                hideStory.Begin();
            }

            Storyboard rectfadeOut = (Storyboard)Resources["blackRectCanvasFadeOut"];
            rectfadeOut.Begin();

            //make sure that any story is closed properly
            foreach (GMapMarker marker in MainMap.Markers)
            {
                if ((marker.Shape as CustomMarker).thisMarkersPopupIsShowing)
                {
                    (marker.Shape as CustomMarker).thisMarkersPopupIsShowing = false;
                }
            }

            mapScrolled = false;
            userIsCurrentlyReadingAStory = false;
        }

        /// <summary>
        /// Shows the filter panel
        /// </summary>
        public void ShowFilterCanvas()
        {
            showFilterPanelImgBtn.Visibility = Visibility.Hidden;
            showButtonRect.Visibility = Visibility.Hidden;
            filterCanvas.Visibility = Visibility.Visible;

            isFilterAnimationRunning = true;
            Storyboard showPanel = (Storyboard)Resources["showFilterPanelStoryboard"];
            showPanel.Begin();
        }

        /// <summary>
        /// Hides the filter panel
        /// </summary>
        public void HideFilterCanvas()
        {
            isFilterAnimationRunning = true;
            Storyboard hidePanel = (Storyboard)Resources["hideFilterPanelStoryboard"];
            hidePanel.Begin();
        }

        /// <summary>
        /// If idle timer ran too many times without user interruption,
        /// that means we can reset the application back to default settings
        /// </summary>
        private void ResetAppToDefaultState()
        {
            howManyTimesCanIdleTimerRunConsequentlyBeforeResetAppToDefaultState = 10;
            readMode = false;
            ResetAllFiltersToSelected();
            HideConfirmPositionCanvas();
            fadeOutHelpCanvas(false);
            fadeOutTermsCanvas();
            HideReadStoryCanvas();
            HideFilterCanvas();
            CloseStoryInput(false);

            MainMap.Zoom = Properties.Settings.Default.MapDefaultZoom;
            //MainMap.Zoom = MainMap.MinZoom;
            panTo(mapCenterPosition, true, 0);
            displayWelcomeScreen();
        }

        /// <summary>
        /// Get new stories that may have been created
        /// since the last update/app launch
        /// </summary>
        private void FetchRecentStories()
        {
           // Cursor = Cursors.Wait;
            Console.WriteLine("Fetching new stories from DB now " + DateTime.Now);
            storyManager.DownloadRecentStoriesIntoDB();
            //Cursor = Cursors.Arrow;
        }

        /// <summary>
        /// Add a story to the remote DB
        /// </summary>
        /// <param name="catID">stories categoryID</param>
        /// <param name="story">story content</param>
        /// <param name="storyPosition">PointLatLng stories markers position</param>
        /// <param name="timeSlotID">timeslotID</param>
        /// <returns></returns>
        private string AddStoryToRemoteDB(int catID, string story, PointLatLng storyPosition, int timeSlotID, string title)
        {
            string reply = storyManager.AddStoryToRemoteDB(catID, story, storyPosition, timeSlotID, machineName, title, internetProblemNotification);
            if (reply.Equals("undefined request!") || reply.Equals(internetProblemNotification))
            {
                ShowGrowlNotification(errorNotification, internetProblemTitle, internetProblemNotification);
                return internetProblemNotification;
            }
            else
            {
                ShowGrowlNotification(newStoryValidation, newStorySuccessTitle, newStorySuccessNotification);
                return reply;
            }
        }

        /// <summary>
        /// Add markers to the map
        /// </summary>
        /// <param name="position">PointLatLng position of the stories marker</param>
        /// <param name="storyText">Story content</param>
        /// <param name="storyCategory">categoryID that story is related to</param>
        /// <param name="showBubbleOnMapAfterAdding">if true, open the stories bubble after added</param>
        /// <param name="storyID">stories ID</param>
        /// <param name="timeslotid">timeslotID</param>
        private void addMarkerToMap(PointLatLng position, string storyText, string storyTitle, int storyCategory, bool showBubbleOnMapAfterAdding, long storyID, int timeslotid, bool isituserstory, string museumImageURL, bool animateMarkerAppearance)
        {
            GMapMarker marker = new GMapMarker(position);
            marker.ZIndex = SQUARE_Z_INDEX + 10;
            //previousPosition = currentPosition;
            previousPosition = position;

            Category cat;
            int indexOfThisStoryCategory = 0;
            bool matchFound = false;
            for (int i = 0; i < categoriesArrayList.Count; i++)
            {
                cat = (Category)categoriesArrayList[i];
                if (cat.CategoryID == storyCategory)
                {
                    indexOfThisStoryCategory = i;
                    matchFound = true;
                    break;
                }
            }
            TimeSlot time;
            int indexOfThisTimeSlot = 0;
            bool timeMatchFound = false;
            for (int i = 0; i < timeSlotArrayList.Count; i++)
            {
                time = (TimeSlot)timeSlotArrayList[i];
                if (time.TimeSlotID == timeslotid)
                {
                    indexOfThisTimeSlot = i;
                    timeMatchFound = true;
                    break;
                }
            }

            if (matchFound && timeMatchFound)
            {
                ////hide any showing markers
                //foreach (GMapMarker mrkr in MainMap.Markers)
                //{
                //    if (!projectorMode)
                //    {
                //        if ((mrkr.Shape as CustomMarker).thisMarkersPopupIsShowing && !(mrkr.Shape as CustomMarker).isItACurrentUserStory)
                //        {
                //            (mrkr.Shape as CustomMarker).hideMarker();
                //        }
                //    }
                //    else
                //    {
                //        if ((mrkr.Shape as CustomMarkerProjector).thisMarkersPopupIsShowing && !(mrkr.Shape as CustomMarkerProjector).showThisBubbleWhenCreating)
                //        {
                //            (mrkr.Shape as CustomMarkerProjector).hideMarker();
                //        }
                //    }
                //}


                cat = (Category)categoriesArrayList[indexOfThisStoryCategory];
                time = (TimeSlot)timeSlotArrayList[indexOfThisTimeSlot];


                if (!projectorMode)
                {
                    if (cat.AdminStory && museumImageURL.Equals(""))//if museum story but with no picture
                    {
                        museumImageURL = "NONE";
                    }

                    CustomMarker customMarker = new CustomMarker(this, marker, cat.MarkerImageSourceNormal, cat.CategoryImageSourceSelected, time.Read_timeslotImg, museumImageURL, storyText, storyTitle, cat.CategoryDesc, storyID, showBubbleOnMapAfterAdding, isituserstory, animateMarkerAppearance);
                    marker.Shape = customMarker;
                }
                else
                {
                    CustomMarkerProjector customMarker = new CustomMarkerProjector(this, marker, cat.MarkerImageSourceNormal, cat.CategoryImageSourceSelected, time.Read_timeslotImg, museumImageURL, storyText, storyTitle, storyID, showBubbleOnMapAfterAdding, isituserstory);
                    marker.Shape = customMarker;
                }

                MainMap.Markers.Add(marker);
            }
        }

        /// <summary>
        /// Create number of required Image Icons (for categories),
        /// put them in the right place,
        /// give them correct tag reference (refering to categoryID)
        /// </summary>
        private void initialiseMarkerIconsWithTags()
        {
            int catChildIndex = 0;
            int catChildIndexInput = 0;
            int maxCategoriesToShowInStackPanel = 6;
            int numCategories = 0;
            //int numCategories = categoriesArrayList.Count;
            foreach (Category i in categoriesArrayList)
            {
                if (numCategories < maxCategoriesToShowInStackPanel && !i.AdminStory) //dont allow admin stories inside the input selection areas
                {
                    //stack panel in story creation box area
                    Image img = new Image();
                    img.Height = 107;
                    img.Width = 136;
                    img.Source = i.CatImgUNSelectedInputBox;
                    img.Tag = i.CategoryID;
                    img.AllowDrop = false;
                    img.Stretch = Stretch.Uniform;
                    img.Opacity = 1;
                    img.MouseDown += new MouseButtonEventHandler(categoryImageBox_mouseDown);


                    if (catChildIndexInput <= 2) //first 3 cats in row 1
                    {
                        Grid.SetRow(img, 0);
                    }
                    else
                    {
                        Grid.SetRow(img, 1); //last 3 cats in row 2
                    }

                    if (catChildIndexInput == 0 || catChildIndexInput == 3)
                    {
                        Grid.SetColumn(img, 0);
                    }
                    else if (catChildIndexInput == 1 || catChildIndexInput == 4)
                    {
                        Grid.SetColumn(img, 2);
                    }
                    else
                    {
                        Grid.SetColumn(img, 4);
                    }
                    categoryTagGrid.Children.Add(img);

                    //categoryIconsStackPanel.Children.Insert(catChildIndex, img);
                    catChildIndexInput++;
                    numCategories++;
                }

                    //also add this to filters area
                    Image img2 = new Image();
                    img2.Height = 75;
                    img2.Source = i.CatImgUNSelectedInputBox;
                    img2.Tag = i.CategoryID;
                    img2.AllowDrop = false;
                    img2.Stretch = Stretch.Uniform;
                    img2.Opacity = 1;
                    img2.MouseDown += new MouseButtonEventHandler(categoryFilterImageBox_mouseDown);
                    img2.MouseLeave += new MouseEventHandler(categoryFilterImageBox_MouseLeave);
                    img2.MouseEnter += new MouseEventHandler(categoryFilterImageBox_MouseEnter);

                    //also add this to filters area
                    TextBlock label = new TextBlock();
                    label.Height = 30;
                    label.Width = 100;
                    label.Text = i.CategoryDesc;
                    label.TextAlignment = TextAlignment.Center;
                    label.AllowDrop = false;
                    label.FontSize = 12;
                    label.FontFamily = new FontFamily("Museo Sans 500");
                    label.IsHitTestVisible = false;
                    label.Margin = new Thickness(-12, 65, 0, 0);
                    label.Foreground = new SolidColorBrush(Color.FromArgb((byte)0xFF, (byte)0x40, (byte)0x81, (byte)0x9B));
                    label.TextWrapping = TextWrapping.Wrap;
                    
                    //filterCategoriesStackPanel.Children.Insert(catChildIndex, img2);

                    if (catChildIndex <= 3) //first 4 cats in row 1
                    {
                        Grid.SetRow(img2, 0);
                        Grid.SetRow(label, 0);
                        img2.Margin = new Thickness(0, -5, 0, 0);
                    }
                    else
                    {
                        Grid.SetRow(img2, 1); //last 3 cats in row 2
                        Grid.SetRow(label, 1); //last 3 cats in row 2
                        img2.Margin = new Thickness(0, -10, 0, 0);
                        label.Margin = new Thickness(-12, 65, 0, 0);
                    }

                    if (catChildIndex == 0)
                    {
                        Grid.SetColumn(img2, 0);
                        Grid.SetColumn(label, 0);
                    }
                    else if (catChildIndex == 1 || catChildIndex == 5)
                    {
                        Grid.SetColumn(img2, 1);
                        Grid.SetColumn(label, 1);
                    }
                    else if (catChildIndex == 2 || catChildIndex == 6)
                    {
                        Grid.SetColumn(img2, 2);
                        Grid.SetColumn(label, 2);
                    }
                    else if (catChildIndex == 3 || catChildIndex == 4)
                    {
                        Grid.SetColumn(img2, 3);
                        Grid.SetColumn(label, 3);
                    }
                    categoryFilterGrid.Children.Add(img2);
                    categoryFilterGrid.Children.Add(label);

                    catChildIndex++;
            }
        }

        /// <summary>
        /// creates the timeslot icons
        /// </summary>
        private void initialiseTimeSlotIconsWithTags()
        {
            int timeSlotChildIndex = 0;
            int maxTimeSlotsToShowInStackPanel = 12;
            int numTimeSlots = 0;
            foreach (TimeSlot i in timeSlotArrayList)
            {
                if (numTimeSlots < maxTimeSlotsToShowInStackPanel)
                {
                    //new story timeslot selection area
                    Image img = new Image();
                    img.Height = 107;
                    img.Width = 136;
                    img.Source = i.TimeSlotImgUnSelected;
                    img.Tag = i.TimeSlotID;
                    img.AllowDrop = false;
                    img.Stretch = Stretch.Uniform;
                    img.Opacity = 0.99;
                    img.MouseDown += new MouseButtonEventHandler(timeslotImageBox_mouseDown);
                    //timelineINPUTStackPanel.Children.Insert(timeSlotChildIndex, img);

                    if (timeSlotChildIndex <= 4) //first 5 timeslots in row 1
                    {
                        Grid.SetRow(img, 0);
                    }
                    else if (timeSlotChildIndex <= 9)
                    {
                        Grid.SetRow(img, 1); //next 5 timeslots in row 2
                    }
                    else
                    {
                        Grid.SetRow(img, 2); //last 2 timeslots in row 3
                    }

                    if (timeSlotChildIndex == 0 || timeSlotChildIndex == 5 || timeSlotChildIndex == 10)
                    {
                        Grid.SetColumn(img, 0);
                    }
                    else if (timeSlotChildIndex == 1 || timeSlotChildIndex == 6 || timeSlotChildIndex == 11)
                    {
                        Grid.SetColumn(img, 1);
                    }
                    else if (timeSlotChildIndex == 2 || timeSlotChildIndex == 7)
                    {
                        Grid.SetColumn(img, 2);
                    }
                    else if (timeSlotChildIndex == 3 || timeSlotChildIndex == 8)
                    {
                        Grid.SetColumn(img, 3);
                    }
                    else if (timeSlotChildIndex == 4 || timeSlotChildIndex == 9)
                    {
                        Grid.SetColumn(img, 4);
                    }
                    timeTagGrid.Children.Add(img);


                    //also add this to filters area
                    Image img2 = new Image();
                    img2.Height = 75;
                    //img2.Width = 138;
                    img2.Source = i.TimeSlotImgUnSelected;
                    img2.Tag = i.TimeSlotID;
                    img2.AllowDrop = false;
                    img2.Stretch = Stretch.Uniform;
                    img2.Opacity = 1;
                    img2.MouseDown += new MouseButtonEventHandler(timeslotFilterImageBox_mouseDown);
                    img2.MouseLeave += new MouseEventHandler(timeslotFilterImageBox_MouseLeave);
                    img2.MouseEnter += new MouseEventHandler(timeslotFilterImageBox_MouseEnter);
                    
                    //timelineFILTERStackPanel.Children.Insert(timeSlotChildIndex, img2);

                    if (timeSlotChildIndex <= 5) //first 6 timeslots in row 1
                    {
                        Grid.SetRow(img2, 0);
                    }
                    else //last 6 in row 2
                    {
                        Grid.SetRow(img2, 1);
                    }

                    if (timeSlotChildIndex == 0 || timeSlotChildIndex == 6)
                    {
                        Grid.SetColumn(img2, 0);
                    }
                    else if (timeSlotChildIndex == 1 || timeSlotChildIndex == 7)
                    {
                        Grid.SetColumn(img2, 1);
                    }
                    else if (timeSlotChildIndex == 2 || timeSlotChildIndex == 8)
                    {
                        Grid.SetColumn(img2, 2);
                    }
                    else if (timeSlotChildIndex == 3 || timeSlotChildIndex == 9)
                    {
                        Grid.SetColumn(img2, 3);
                    }
                    else if (timeSlotChildIndex == 4 || timeSlotChildIndex == 10)
                    {
                        Grid.SetColumn(img2, 4);
                    }
                    else if (timeSlotChildIndex == 5 || timeSlotChildIndex == 11)
                    {
                        Grid.SetColumn(img2, 5);
                    }
                    timeslotFilterGrid.Children.Add(img2);
                    

                    timeSlotChildIndex++;
                    numTimeSlots++;
                }
            }
        }
        
        void categoryFilterImageBox_MouseEnter(object sender, MouseEventArgs e)
        {
            scale.From = 1;
            scale.To = 1.05;

            ScaleTransform oTransform = new ScaleTransform();
            (sender as Image).RenderTransform = (Transform)oTransform;
            oTransform.BeginAnimation(ScaleTransform.ScaleXProperty, scale);
            oTransform.BeginAnimation(ScaleTransform.ScaleYProperty, scale);

            touchLeaveTimeout.Stop();
            touchLeaveTimeout.Tick -= new EventHandler(touchLeaveTimeout_Tick);
            if (isFilterTouchDown)
            {
                //if (!markerRedrawTimer.Enabled)
                //{
                if ((sender as Image).Opacity == 1)
                {
                    foreach (Category category in categoriesArrayList)
                    {
                        if (Convert.ToInt32((sender as Image).Tag) == category.CategoryID)
                        {
                            category.ShowFilter = false;
                        }
                    }
                    (sender as Image).Opacity = 0.99;
                    //now update its image to suit
                    (sender as Image).Source = GetCategoryImageByID(false, true, Convert.ToInt32((sender as Image).Tag));
                }
                else
                {
                    foreach (Category category in categoriesArrayList)
                    {
                        if (Convert.ToInt32((sender as Image).Tag) == category.CategoryID)
                        {
                            category.ShowFilter = true;
                        }
                    }
                    (sender as Image).Opacity = 1;
                    (sender as Image).Source = GetCategoryImageByID(true, true, Convert.ToInt32((sender as Image).Tag));
                }
                //}
            }

        }

        void categoryFilterImageBox_MouseLeave(object sender, MouseEventArgs e)
        {
            scale.From = 1.05;
            scale.To = 1;

            ScaleTransform oTransform = new ScaleTransform();
            (sender as Image).RenderTransform = oTransform;
            oTransform.BeginAnimation(ScaleTransform.ScaleXProperty, scale);
            oTransform.BeginAnimation(ScaleTransform.ScaleYProperty, scale);

            if (mouseDown)
            {
                touchLeaveTimeout.Interval = 2000;
                touchLeaveTimeout.Tick += new EventHandler(touchLeaveTimeout_Tick);
                touchLeaveTimeout.Start();
            }

        }
        
        void timeslotFilterImageBox_MouseEnter(object sender, MouseEventArgs e)
        {
            scale.From = 1;
            scale.To = 1.05;

            ScaleTransform oTransform = new ScaleTransform();
            (sender as Image).RenderTransform = oTransform;
            oTransform.BeginAnimation(ScaleTransform.ScaleXProperty, scale);
            oTransform.BeginAnimation(ScaleTransform.ScaleYProperty, scale);

            touchLeaveTimeout.Stop();
            touchLeaveTimeout.Tick -= new EventHandler(touchLeaveTimeout_Tick);
            if (isFilterTouchDown)
            {
                //if (!markerRedrawTimer.Enabled)
                //{
                if ((sender as Image).Opacity == 1)
                {
                    foreach (TimeSlot timeslot in timeSlotArrayList)
                    {
                        if (Convert.ToInt32((sender as Image).Tag) == timeslot.TimeSlotID)
                        {
                            timeslot.ShowFilter = false;
                        }
                    }
                    (sender as Image).Opacity = 0.99;
                    (sender as Image).Source = GetTimeSlotImageByID(true, Convert.ToInt32((sender as Image).Tag));
                }
                else
                {
                    foreach (TimeSlot timeslot in timeSlotArrayList)
                    {
                        if (Convert.ToInt32((sender as Image).Tag) == timeslot.TimeSlotID)
                        {
                            timeslot.ShowFilter = true;
                        }
                    }
                    (sender as Image).Opacity = 1;
                    (sender as Image).Source = GetTimeSlotImageByID(false, Convert.ToInt32((sender as Image).Tag));
                }
                //}
            }
        }

        void timeslotFilterImageBox_MouseLeave(object sender, MouseEventArgs e)
        {
            scale.From = 1.05;
            scale.To = 1;

            ScaleTransform oTransform = new ScaleTransform();
            (sender as Image).RenderTransform = oTransform;
            oTransform.BeginAnimation(ScaleTransform.ScaleXProperty, scale);
            oTransform.BeginAnimation(ScaleTransform.ScaleYProperty, scale);


            if (mouseDown)
            {
                touchLeaveTimeout.Interval = 2000;
                touchLeaveTimeout.Tick += new EventHandler(touchLeaveTimeout_Tick);
                touchLeaveTimeout.Start();
            }
        }

        //handles for when user moves input (mouse/touch) away from the sender object
        bool updatingFiltersInDB = false;
        bool shoulditReload = false;
        void Window_MouseUp(object sender, MouseButtonEventArgs e)
        {
            if (!welcomeActive)
            {
                idleTimer.Stop();
                idleTimer.Start();
                idleTimerRunCount = 0;
            }

            touchLeaveTimeout.Stop();
            touchLeaveTimeout.Tick -= new EventHandler(touchLeaveTimeout_Tick);

            mouseDown = false;

            if (blackRectangleCanvas.Visibility != Visibility.Visible && whiteRectangleCanvas.Visibility != Visibility.Visible && !projectorMode)
            {
                if (isFilterTouchDown)
                {
                    if (!updatingFiltersInDB)
                    {
                        updatingFiltersInDB = true;
                        storyManager.UpdateAllCategoryFilterStatus(categoriesArrayList, false);
                        storyManager.UpdateAllTimeSlotFilterStatus(timeSlotArrayList, false);
                        ReloadStories(true);
                        isFilterTouchDown = false;
                        idleTimer.Stop();
                        idleTimer.Start();
                        updatingFiltersInDB = false;
                    }
                }
                else
                {
                    shoulditReload = true;

                    //if they have gone outside of auckland, bring them back
                    if (!theCityBoundary.Contains(MainMap.Position) && !mapIsPanning && shoulditReload)
                    {
                        positionToPanTo.Lat = MainMap.Position.Lat; positionToPanTo.Lng = MainMap.Position.Lng;
                        if (MainMap.Position.Lat > auckTopLat) //above auck
                        {
                            positionToPanTo.Lat = auckTopLat;
                        }
                        else if (MainMap.Position.Lat < auckBottomLat) //below auck
                        {
                            positionToPanTo.Lat = auckBottomLat;
                        }
                        if (MainMap.Position.Lng < auckLeft) //too far left
                        {
                            positionToPanTo.Lng = auckLeft;
                        }
                        else if (MainMap.Position.Lng > auckRight) //too far right
                        {
                            positionToPanTo.Lng = auckRight;
                        }

                        //if (panTo(mapCenterPosition, true))
                        if (panTo(positionToPanTo, true, 0))
                        {
                           reloadAfterPan = true;
                        }
                    }
                    if (shouldReloadOnTouch && shoulditReload && !mapIsPanning)
                    {
                        if (mapScrolled)
                         {
                            ReloadStories(false);
                            mapScrolled = false;
                        }

                        idleTimer.Stop();
                        idleTimer.Start();
                        idleTimerRunCount = 0;
                    }
                }
            }
        }
        PointLatLng positionToPanTo = new PointLatLng();

        private void FindNextSpellingError()
        {
            if (addStoryTextCanvas.Visibility == System.Windows.Visibility.Visible)
            {
                storyInputTextBox.CaretIndex = 0;
                // Find the next spelling error and show the list of suggestions for it.
                int caretIdx = storyInputTextBox.CaretIndex;
                int idx = storyInputTextBox.GetNextSpellingErrorCharacterIndex(caretIdx, LogicalDirection.Forward);
                if (idx > -1)
                {

                    storyInputTextBox.CaretIndex = idx;
                    sendF1();
                }
            }
        }

        #region Mainwindow action/feedback stuff
        void MainMap_OnCurrentPositionChanged(PointLatLng point)
        {
            if (!mapIsPanning) //if map is scrolling by the user
            {
                mapScrolled = true;
            }

            ////if they have gone outside of auckland, bring them back
            //if (!theCityBoundary.Contains(MainMap.Position) && !mapIsPanning)
            //{
            //    panTo(mapCenterPosition, true);
            //}
        }

        void MainMap_OnMapZoomChanged()
        {
            if (!projectorMode)
            {
                idleTimer.Stop();
                idleTimer.Start();
                idleTimerRunCount = 0;
                ReloadStories(true);
            }
        }

        /// <summary>
        /// When something is dropped onto the map, convert its dropped position from local to longitude & lattitude position
        /// for processing by the map component
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MainMap_Drop(object sender, DragEventArgs e)
        {
            System.Windows.Point p = e.GetPosition(MainMap);
            currentPosition = MainMap.FromLocalToLatLng((int)p.X, (int)p.Y);
            Cursor = Cursors.Arrow;

            if (e.Effects == DragDropEffects.Copy)
            {
                addStoryMarker.Visibility = Visibility.Visible;
                addStoryMarker.VerticalAlignment = System.Windows.VerticalAlignment.Top;
                addStoryMarker.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;

                addStoryMarker.Margin = new Thickness(p.X - (addStoryMarker.Width / 2), p.Y - (addStoryMarker.Height), 0, 0);

                //ReloadStories(false);//if there was any bubbles showing, it will close now
                //NewInputStory(false);
                ShowConfirmPositionCanvas();
            }
            else
            {
                addStoryMarker.VerticalAlignment = System.Windows.VerticalAlignment.Bottom;
                addStoryMarker.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
                addStoryMarker.Margin = new Thickness(20, 0, 0, 100); //go back to centre screen
                addStoryMarker.Visibility = Visibility.Visible;
            }
        }

        private void Window_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == System.Windows.Input.Key.Add)
            {
                MainMap.Bearing--;
            }
            else if (e.Key == System.Windows.Input.Key.Subtract)
            {
                MainMap.Bearing++;
            }
            else if (e.Key == System.Windows.Input.Key.F2)
            {
                ManageAppSettings manageWindow = new ManageAppSettings();
                manageWindow.Show();
            }
            else if (e.Key == System.Windows.Input.Key.F3)
            {
                FindNextSpellingError();
            }

            //Sounds.playSound("click_sound0.wav");
        }

        private void window_PreviewGiveFeedback(object sender, GiveFeedbackEventArgs e)
        {
            try
            {
                if (e.Effects == DragDropEffects.None)
                {
                    Mouse.SetCursor(((FrameworkElement)this.Resources["CursorNewStoryCantDrop"]).Cursor);
                }
                else
                {
                    Mouse.SetCursor(((FrameworkElement)this.Resources["CursorNewStoryDrag"]).Cursor);
                }
                e.UseDefaultCursors = false;

            }
            finally { e.Handled = true; }
        }
        #endregion

        #region Interface element actions
        
        private void timeslotImageBox_mouseDown(object sender, MouseButtonEventArgs e)
        {
            resetStateofPreviouslySelectedTimeSlotImg();
            previousTimeSlotSender = sender;
            currentTimeSlotType = Convert.ToInt32((sender as Image).Tag);
            (sender as Image).Opacity = 1;
            (sender as Image).Source = GetTimeSlotImageByID(true, Convert.ToInt32((sender as Image).Tag));
            aTimeSlotHasBeenSelected = true;
            VerifyIfStoryCanBeSubmitted(false);
        }

        private void resetStateofPreviouslySelectedTimeSlotImg()
        {
            if (previousTimeSlotSender != null)
            {
                (previousTimeSlotSender as Image).Opacity = 0.99;
                (previousTimeSlotSender as Image).Source = GetTimeSlotImageByID(false, Convert.ToInt32((previousTimeSlotSender as Image).Tag));
            }
        }

        private void categoryImageBox_mouseDown(object sender, MouseButtonEventArgs e)
        {
            resetStateofPreviouslySelectedCategoryImg_ForInputBox();
            previousCategorySender = sender;
            currentStoryType = Convert.ToInt32((sender as Image).Tag);
            (sender as Image).Source = GetCategoryImageByID(true, false, Convert.ToInt32((sender as Image).Tag));
            currentlySelectedCat.Source = (sender as Image).Source;
            aCategoryHasBeenSelected = true;
            VerifyIfStoryCanBeSubmitted(false);
        }

        private void resetStateofPreviouslySelectedCategoryImg_ForInputBox()
        {
            if (previousCategorySender != null)
            {
                //make that previous image use the stored unselected image
                (previousCategorySender as Image).Source = GetCategoryImageByID(false, false, Convert.ToInt32((previousCategorySender as Image).Tag));
            }
        }

        /// <summary>
        /// Get the ImageSource reference for the image you want (related to a Category)
        /// </summary>
        /// <param name="selectedImage">Do you want the selected or unselected version?</param>
        /// <param name="tagID">in other words, timeslotID</param>
        /// <returns>ImageSource of the image you want</returns>
        private ImageSource GetTimeSlotImageByID(bool selectedImage, int tagID)
        {
            TimeSlot time;
            int indexOfThisTimeSlot = 0;
            bool matchFound = false;
            for (int i = 0; i < timeSlotArrayList.Count; i++)
            {
                time = (TimeSlot)timeSlotArrayList[i];
                if (time.TimeSlotID == tagID)
                {
                    indexOfThisTimeSlot = i;
                    matchFound = true;
                }
            }
            if (matchFound)
            {
                time = (TimeSlot)timeSlotArrayList[indexOfThisTimeSlot];
                if (selectedImage)
                {
                    return time.TimeSlotImageSourceSelected;
                }
                else
                {
                    return time.TimeSlotImgUnSelected;
                }
            }
            else
            {
                return new BitmapImage(new Uri("/InteractiveMapApp;component/Images/darkGreenTrees.png", UriKind.Relative));
            }

        }

        /// <summary>
        /// Get the ImageSource reference for the image you want (related to a Category)
        /// </summary>
        /// <param name="selectedimage">Do you want the selected or unselected version?</param>
        /// <param name="filterArea">is it in filtered area? or inputbox?</param>
        /// <param name="tagID">in other words, categoryID</param>
        /// <returns>ImageSource of the image you want</returns>
        private ImageSource GetCategoryImageByID(bool selectedimage, bool filterArea, int tagID)
        {
            Category cat;
            int indexOfThisStoryCategory = 0;
            bool matchFound = false;
            for (int i = 0; i < categoriesArrayList.Count; i++)
            {
                cat = (Category)categoriesArrayList[i];
                if (cat.CategoryID == tagID)
                {
                    indexOfThisStoryCategory = i;
                    matchFound = true;
                }
            }
            if (matchFound)
            {
                cat = (Category)categoriesArrayList[indexOfThisStoryCategory];
                if (selectedimage)
                {
                    if (filterArea)
                    {
                        return cat.CatImgUNSelectedInputBox;
                    }
                    else //inputbox
                    {
                        return cat.CatImgSELECTEDInputBox;
                    }
                }
                else
                {
                    if (filterArea)
                    {
                        return cat.CatImgSELECTEDInputBox;
                    }
                    else //inputbox
                    {
                        return cat.CatImgUNSelectedInputBox;
                    }
                }
            }
            else //you'd hope it should never come to this.. but just in case..
            {
                return new BitmapImage(new Uri("/InteractiveMapApp;component/Images/darkGreenTrees.png", UriKind.Relative));
            }
        }

        private void timeslotFilterImageBox_mouseDown(object sender, MouseButtonEventArgs e)
        {
            idleTimer.Stop();

            mouseDown = true;

            isFilterTouchDown = !isFilterTouchDown;

            prevCategoriesArrayList = new ArrayList();
            foreach (Category category in categoriesArrayList)
            {
                for (int i = 0; i < timeslotFilterGrid.Children.Count; i++)
                {
                    if (Convert.ToInt32((timeslotFilterGrid.Children[i] as Image).Tag) == category.CategoryID)
                    {
                        Category temp;
                        temp = (Category)category.Clone();
                        prevCategoriesArrayList.Add(temp);
                    }
                }
            }

            prevTimeSlotArrayList = new ArrayList();
            foreach (TimeSlot timeslot in timeSlotArrayList)
            {
                for (int i = 0; i < timeslotFilterGrid.Children.Count; i++)
                {
                    if (Convert.ToInt32((timeslotFilterGrid.Children[i] as Image).Tag) == timeslot.TimeSlotID)
                    {
                        TimeSlot temp;
                        temp = (TimeSlot)timeslot.Clone();
                        prevTimeSlotArrayList.Add(temp);
                    }
                }
            }

            if ((sender as Image).Opacity == 1)
            {
                foreach (TimeSlot timeslot in timeSlotArrayList)
                {
                    if (Convert.ToInt32((sender as Image).Tag) == timeslot.TimeSlotID)
                    {
                        timeslot.ShowFilter = false;
                    }
                }
                (sender as Image).Opacity = 0.99;
                (sender as Image).Source = GetTimeSlotImageByID(true, Convert.ToInt32((sender as Image).Tag));
            }
            else
            {
                foreach (TimeSlot timeslot in timeSlotArrayList)
                {
                    if (Convert.ToInt32((sender as Image).Tag) == timeslot.TimeSlotID)
                    {
                        timeslot.ShowFilter = true;
                    }
                }
                (sender as Image).Opacity = 1;
                (sender as Image).Source = GetTimeSlotImageByID(false, Convert.ToInt32((sender as Image).Tag));
            }
        }

        private void categoryFilterImageBox_mouseDown(object sender, MouseButtonEventArgs e)
        {
            idleTimer.Stop();

            mouseDown = true;

            isFilterTouchDown = !isFilterTouchDown;

            prevCategoriesArrayList = new ArrayList();
            foreach (Category category in categoriesArrayList)
            {
                for (int i = 0; i < categoryFilterGrid.Children.Count; i++)
                {
                    if ((categoryFilterGrid.Children[i] is Image))
                    {
                        if (Convert.ToInt32((categoryFilterGrid.Children[i] as Image).Tag) == category.CategoryID)
                        {
                            Category temp;
                            temp = (Category)category.Clone();
                            prevCategoriesArrayList.Add(temp);
                            break;
                        }
                    }
                }
            }

            prevTimeSlotArrayList = new ArrayList();
            foreach (TimeSlot timeslot in timeSlotArrayList)
            {
                for (int i = 0; i < timeslotFilterGrid.Children.Count; i++)
                {
                    if (Convert.ToInt32((timeslotFilterGrid.Children[i] as Image).Tag) == timeslot.TimeSlotID)
                    {
                        TimeSlot temp;
                        temp = (TimeSlot)timeslot.Clone();
                        prevTimeSlotArrayList.Add(temp);
                    }
                }
            }


            if ((sender as Image).Opacity == 1)
            {
                foreach (Category category in categoriesArrayList)
                {
                    if (Convert.ToInt32((sender as Image).Tag) == category.CategoryID)
                    {
                        category.ShowFilter = false;
                    }
                }
                (sender as Image).Opacity = 0.99;
                (sender as Image).Source = GetCategoryImageByID(false, true, Convert.ToInt32((sender as Image).Tag));
            }
            else
            {
                foreach (Category category in categoriesArrayList)
                {
                    if (Convert.ToInt32((sender as Image).Tag) == category.CategoryID)
                    {
                        category.ShowFilter = true;
                    }

                }
                (sender as Image).Opacity = 1;
                (sender as Image).Source = GetCategoryImageByID(true, true, Convert.ToInt32((sender as Image).Tag));
            }
        }

        private void helpBtn_MouseDown(object sender, MouseButtonEventArgs e)
        {
            areButtonsBeingUsed = true;
            helpBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_help_down.png", UriKind.Relative));
        }
        private void helpBtn_MouseUp(object sender, MouseButtonEventArgs e)
        {
            helpBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_help_up.png", UriKind.Relative));

            if (helpDialogueCanvas.Visibility == Visibility.Hidden)
            {
                shouldReloadOnTouch = false;
                helpDialogueCanvas.Visibility = Visibility.Visible;
                helpDialogueCanvas.Opacity = 0;
                Storyboard fadeIn = (Storyboard)Resources["HelpCanvasFadeIn"];
                fadeIn.Begin();

                //plus the rectangle behind it
                blackRectangleCanvas.Visibility = System.Windows.Visibility.Visible;
                blackRectangleCanvas.Opacity = 0;
                blackRectangleCanvas.Height = window.Height;
                blackRectangleCanvas.Width = window.Width;
                Storyboard fadeInRect = (Storyboard)Resources["blackRectCanvasDarkFadeIn"];
                fadeInRect.Begin();
            }
            else
            {
                fadeOutHelpCanvas(false);
            }
        }
        private void helpBtn_MouseLeave(object sender, MouseEventArgs e)
        {
            if (areButtonsBeingUsed)
            {
                helpBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_help_up.png", UriKind.Relative));
                areButtonsBeingUsed = false;
            }
        }

        private void fadeOutHelpCanvas(bool dontfadeblack)
        {
            if (!dontfadeblack)
            {
                Storyboard rectfadeOut = (Storyboard)Resources["blackRectCanvasFadeOut"];
                rectfadeOut.Begin();
                shouldReloadOnTouch = true;
            }

            Storyboard fadeOut = (Storyboard)Resources["HelpCanvasFadeOut"];
            fadeOut.Begin();
        }
        private void fadeOutTermsCanvas()
        {
            Storyboard fadeOut = (Storyboard)Resources["TermsCanvasFadeOut"];
            fadeOut.Begin();
        }
        private void fadingOutHelpCanvas_Completed(object sender, EventArgs e)
        {
            helpDialogueCanvas.Visibility = Visibility.Hidden;
            howManyTimesCanIdleTimerRunConsequentlyBeforeResetAppToDefaultState = 10;
        }
        private void fadingOutTermsCanvas_Completed(object sender, EventArgs e)
        {
            termsOfUseCanvas.Visibility = Visibility.Hidden;

            if (helpDialogueCanvas.Visibility == Visibility.Hidden)
            {
                howManyTimesCanIdleTimerRunConsequentlyBeforeResetAppToDefaultState = 10;
            }
        }

        private void zoomOutBtn_MouseDown(object sender, MouseButtonEventArgs e)
        {
            areButtonsBeingUsed = true;
            zoomTimer.Interval = 500;
            if (MainMap.Zoom == MainMap.MinZoom)
            {
                //MainMap.Position = mapCenterPosition;
                if (panTo(mapCenterPosition, false, 0))
                {
                    reloadAfterPan = true;
                }
            }
            zoomTimer.Tick += new EventHandler(zoomOutTimer_Tick);
            zoomTimer.Start();
            zoomOutBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_zoomout_down.png", UriKind.Relative));
        }
        private void zoomOutBtn_MouseUp(object sender, MouseButtonEventArgs e)
        {
            zoomOutBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_zoomout_up.png", UriKind.Relative));

            if (zoomTimer.Enabled)
            {
                zoomTimer.Stop();
                zoomTimer.Tick -= new EventHandler(zoomOutTimer_Tick);
            }
            if (zoomTimer.Interval == 500)//for single zoom tap --500 means it hasn't cycled through the timer
            {
                MainMap.Zoom -= 1;
            }
            MainMap.Zoom = Math.Floor(MainMap.Zoom);//rounds the zoom level down to the next level if it is a fractional value (ie. 12.8 -- 12)
            areButtonsBeingUsed = false;
        }
        private void zoomOutBtn_MouseLeave(object sender, MouseEventArgs e)
        {
            if (areButtonsBeingUsed)
            {
                zoomOutBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_zoomout_up.png", UriKind.Relative));

                if (zoomTimer.Enabled)
                {
                    zoomTimer.Stop();
                    zoomTimer.Tick -= new EventHandler(zoomOutTimer_Tick);
                }
                if (zoomTimer.Interval == 500)//for single zoom tap --500 means it hasn't cycled through the timer
                {
                    MainMap.Zoom -= 1;
                }
                MainMap.Zoom = Math.Floor(MainMap.Zoom);//rounds the zoom level down to the next level if it is a fractional value (ie. 12.8 -- 12)
                areButtonsBeingUsed = false;
            }
        }
        private void zoomInBtn_MouseDown(object sender, MouseButtonEventArgs e)
        {
            areButtonsBeingUsed = true;
            zoomTimer.Interval = 500;
            zoomTimer.Tick += new EventHandler(zoomInTimer_Tick);
            zoomTimer.Start();
            zoomInBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_zoomin_down.png", UriKind.Relative));
        }
        private void zoomInBtn_MouseUp(object sender, MouseButtonEventArgs e)
        {
            zoomInBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_zoomin_up.png", UriKind.Relative));

            if (zoomTimer.Enabled)
            {
                zoomTimer.Stop();
                zoomTimer.Tick -= new EventHandler(zoomInTimer_Tick);
            }
            if (zoomTimer.Interval == 500)//for single zoom tap --500 means it hasn't cycled through the timer
            {
                MainMap.Zoom += 1;

            }
            MainMap.Zoom = Math.Ceiling(MainMap.Zoom);//rounds the zoom level up to the next level if it is a fractional value (ie. 12.2 -- 13)
            areButtonsBeingUsed = false;
        }
        private void zoomInBtn_MouseLeave(object sender, MouseEventArgs e)
        {
            if (areButtonsBeingUsed)
            {
                zoomInBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_zoomin_up.png", UriKind.Relative));

                if (zoomTimer.Enabled)
                {
                    zoomTimer.Stop();
                    zoomTimer.Tick -= new EventHandler(zoomInTimer_Tick);
                }
                if (zoomTimer.Interval == 500)//for single zoom tap --500 means it hasn't cycled through the timer
                {
                    MainMap.Zoom += 1;

                }
                MainMap.Zoom = Math.Ceiling(MainMap.Zoom);//rounds the zoom level up to the next level if it is a fractional value (ie. 12.2 -- 13)
                areButtonsBeingUsed = false;
            }
        }

        private void helpCanvasExitImageBtn_MouseUp(object sender, MouseButtonEventArgs e)
        {
            fadeOutHelpCanvas(false);
            helpCanvasExitImageBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_X.png", UriKind.Relative));
        }
        private void helpCanvasExitImageBtn_MouseDown(object sender, MouseButtonEventArgs e)
        {
            helpCanvasExitImageBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_X_down.png", UriKind.Relative));
        }
        private void helpCanvasExitImageBtn_MouseLeave(object sender, MouseEventArgs e)
        {
            helpCanvasExitImageBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_X.png", UriKind.Relative));
        }

        private void storyInputTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (storyInputTextBox.CaretIndex > 0)
            {
                if (storyTitleInputTextBox.AreSuggestionsVisible)
                {
                    storyTitleInputTextBox.HideSuggestions();
                }

                int idx = storyInputTextBox.CaretIndex - 1;
                SpellingError error = storyInputTextBox.GetSpellingError(idx);
                if (error != null)
                {
                    suggestionsListbox.ItemsSource = error.Suggestions;
                    idx += 1;
                    while (idx > 0)
                    {
                        char prevChar = storyInputTextBox.Text[idx - 1];
                        if (char.IsWhiteSpace(prevChar) || char.IsPunctuation(prevChar))
                            break;
                        --idx;
                    }
                    //make it visible if there is something to show
                    if (suggestionsListbox.Items.Count > 0)
                    {
                        storyInputTextBox.ShowSuggestions();
                    }
                    else
                    {
                        if (storyInputTextBox.AreSuggestionsVisible)
                        {
                            storyInputTextBox.HideSuggestions();
                        }
                    }
                }
                else
                {
                    suggestionsListbox.ItemsSource = null;
                    if (storyInputTextBox.AreSuggestionsVisible)
                    {
                        storyInputTextBox.HideSuggestions();
                    }
                }
            }
            VerifyIfStoryCanBeSubmitted(false);
            charsRemainingLbl.Content = storyInputTextBox.Text.Length.ToString() + " / " + storyInputTextBox.MaxLength.ToString();
            if (storyInputTextBox.Text.Length >= storyInputTextBox.MaxLength)
            {
                charsRemainingLbl.Foreground = Brushes.Red;
            }
            else
            {
                charsRemainingLbl.Foreground = Brushes.Black;
            }
        }
        private void storyTitleInputTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (storyTitleInputTextBox.CaretIndex > 0)
            {
                if (storyInputTextBox.AreSuggestionsVisible)
                {
                    storyInputTextBox.HideSuggestions();
                }

                int idx = storyTitleInputTextBox.CaretIndex - 1;
                SpellingError error = storyTitleInputTextBox.GetSpellingError(idx);
                if (error != null)
                {
                    suggestionsListbox.ItemsSource = error.Suggestions;
                    idx += 1;
                    while (idx > 0)
                    {
                        char prevChar = storyTitleInputTextBox.Text[idx - 1];
                        if (char.IsWhiteSpace(prevChar) || char.IsPunctuation(prevChar))
                            break;
                        --idx;
                    }
                    //make it visible if there is something to show
                    if (suggestionsListbox.Items.Count > 0)
                    {
                        storyTitleInputTextBox.ShowSuggestions();
                    }
                    else
                    {
                        if (storyTitleInputTextBox.AreSuggestionsVisible)
                        {
                            storyTitleInputTextBox.HideSuggestions();
                        }
                    }
                }
                else
                {
                    suggestionsListbox.ItemsSource = null;
                    if (storyTitleInputTextBox.AreSuggestionsVisible)
                    {
                        storyTitleInputTextBox.HideSuggestions();
                    }
                }
            }
            VerifyIfStoryCanBeSubmitted(false);
            charsRemainingLbl.Content = storyTitleInputTextBox.Text.Length.ToString() + " / " + storyTitleInputTextBox.MaxLength.ToString();
            if (storyTitleInputTextBox.Text.Length >= storyTitleInputTextBox.MaxLength)
            {
                charsRemainingLbl.Foreground = Brushes.Red;
            }
            else
            {
                charsRemainingLbl.Foreground = Brushes.Black;
            }
        }
        private void storyTitleInputTextBox_GotFocus(object sender, RoutedEventArgs e)
        {
            if (storyInputTextBox.AreSuggestionsVisible)
            {
                storyInputTextBox.HideSuggestions();
            }
        }
        private void storyInputTextBox_GotFocus(object sender, RoutedEventArgs e)
        {
            if (storyTitleInputTextBox.AreSuggestionsVisible)
            {
                storyTitleInputTextBox.HideSuggestions();
            }
        }


        private void shareStoryImgBtn_MouseDown(object sender, MouseButtonEventArgs e)
        {
            shareStoryImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_touchshare_down.png", UriKind.Relative));
        }

        ///// <summary>
        ///// submits input story
        ///// uploads to database, adds to user arraylist and adds to map
        ///// </summary>
        ///// <param name="sender"></param>
        ///// <param name="e"></param>
        //private void shareStoryImgBtn_MouseUp(object sender, MouseButtonEventArgs e)
        //{
        //    if (IsItASecretAdminCommand(storyInputTextBox.Text))
        //    {
        //        CloseStoryInput();
        //    }
        //    else //its not an admin command
        //    {
        //        if (VerifyIfStoryCanBeSubmitted(true))
        //        {

        //            Cursor = Cursors.Wait;
        //            string filteredStory = AddStoryToRemoteDB(currentStoryType, FilterTheStoryFromBadChars(storyInputTextBox.Text), currentPosition, currentTimeSlotType, storyTitleInputTextBox.Text);


        //            string[] tempStory = filteredStory.Split(stringSplitChar);


        //            filteredStory = tempStory[0];
        //            myStoryLifetime.Stop();
        //            myStoryLifetime.Elapsed -= new System.Timers.ElapsedEventHandler(myStoryLifetime_Elapsed);//remove any existing timer
        //            myStoryLifetime.Elapsed += new System.Timers.ElapsedEventHandler(myStoryLifetime_Elapsed);
        //            myStoryLifetime.Interval = UserStoryLifetime;
        //            myStoryLifetime.Start();
        //            Cursor = Cursors.Arrow;

        //            try
        //            {
        //                long idOfNewStory = Convert.ToInt64(tempStory[1]);
        //                if (tempStory[1].Equals("-1")) //-1 id means story matched filtered words
        //                {
        //                    //show message to user
        //                    addMarkerToMap(currentPosition, "", currentStoryType, true, idOfNewStory, currentTimeSlotType, true, null);
        //                }
        //                else
        //                {
        //                    addMarkerToMap(currentPosition, filteredStory, currentStoryType, true, idOfNewStory, currentTimeSlotType, true, null);
        //                }
        //                Story temp = new Story(idOfNewStory, currentStoryType, currentTimeSlotType, currentPosition.Lat, currentPosition.Lng, filteredStory, null, title);
        //                myStoriesArrayList.Add(temp);
        //                sendUpdateMessage(temp);//send update message
        //            }
        //            catch
        //            {
        //                //if there was an error, still add the story but show error message
        //                addMarkerToMap(currentPosition, filteredStory, currentStoryType, true, -1, currentTimeSlotType, true, null);
        //            }

        //            CloseStoryInput();
        //        }
        //    }
        //    shareStoryImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_touchshare.png", UriKind.Relative));
        //    e.Handled = true;
        //}

        /// <summary>
        /// Checks if the input was a secret admin command
        /// and take appropriate action for it
        /// </summary>
        /// <param name="theText">string to check</param>
        /// <returns>true if its admin command, false if not</returns>
        private bool IsItASecretAdminCommand(string theText)
        {
            if (theText.Equals("/admin2626 update"))
            {
                MessageBox.Show("Downloading new stories from Remote DB now.");
                FetchRecentStories();
                return true;
            }
            else if (theText.Equals("/secret secret"))
            {
                MessageBox.Show("Secret Method for Project Group 26!");
                return true;
            }
            else if (theText.Equals("/admin2626 keyboard"))
            {
                showTheAdminKeyboard();
                return true;
            }
            else if (theText.Equals("/admin2626 exit"))
            {
                System.Windows.Application.Current.Shutdown();
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// Brings up windows on screen keyboard
        /// admin needs this special one rather than our one because it has acess to special keys like
        /// the FN keys so he can access the admin area etc. Windows kbd is also draggable whereas ours isnt.
        /// </summary>
        private void showTheAdminKeyboard()
        {
            try
            {
                string windir = Environment.GetEnvironmentVariable("WINDIR");
                string osk = null;

                if (osk == null)
                {
                    osk = Path.Combine(Path.Combine(windir, "sysnative"), "osk.exe");
                    if (!File.Exists(osk))
                    {
                        osk = null;
                    }
                }

                if (osk == null)
                {
                    osk = Path.Combine(Path.Combine(windir, "system32"), "osk.exe");
                    if (!File.Exists(osk))
                    {
                        osk = null;
                    }
                }

                if (osk == null)
                {
                    osk = "osk.exe";
                }

                Process.Start(osk);
            }
            catch { MessageBox.Show("Virtual Keyboard has failed to start. Please plug in a real one."); }
        }

        private void cancelStoryInputImgBtn_MouseUp(object sender, MouseButtonEventArgs e)
        {
            CloseStoryInput(false);
        }
        private void cancelStoryInputImgBtn_MouseLeave(object sender, MouseEventArgs e)
        {
            cancelStoryInputImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_X.png", UriKind.Relative));
        }
        private void cancelStoryInputImgBtn_MouseDown(object sender, MouseButtonEventArgs e)
        {
            cancelStoryInputImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_X_down.png", UriKind.Relative));
        }

        private void fadingOutTextStoryInput_Completed(object sender, EventArgs e)
        {
            addStoryTextCanvas.Visibility = System.Windows.Visibility.Hidden;
            CloseKeyboard();
        }
        private void fadingOutTimeStoryInput_Completed(object sender, EventArgs e)
        {
            addStoryTimeCanvas.Visibility = System.Windows.Visibility.Hidden;
        }
        private void fadingOutCatStoryInput_Completed(object sender, EventArgs e)
        {
            addStoryCatCanvas.Visibility = System.Windows.Visibility.Hidden;
        }

        private void blackRectCanvasFadeOut_Completed(object sender, EventArgs e)
        {
            blackRectangleCanvas.Visibility = System.Windows.Visibility.Hidden;
        }
        private void whiteRectCanvasFadeOut_Completed(object sender, EventArgs e)
        {
            whiteRectangleCanvas.Visibility = System.Windows.Visibility.Hidden;
        }

        private void CategoryInputFadeInThenOut_Completed(object sender, EventArgs e)
        {
            pulseOverCategories.Opacity = 0;
            pulseOverCategories.Visibility = System.Windows.Visibility.Collapsed;
        }
        private void StoryInputFadeInThenOut_Completed(object sender, EventArgs e)
        {
            pulseOverStory.Opacity = 0;
            pulseOverStory.Visibility = System.Windows.Visibility.Collapsed;
        }
        private void TimeSlotInputFadeInThenOut_Completed(object sender, EventArgs e)
        {
            pulseOverTimeSlot.Opacity = 0;
            pulseOverTimeSlot.Visibility = System.Windows.Visibility.Collapsed;
        }

        #endregion
        
        #region projector specific methods
        DateTime baseTime = DateTime.Now;
        /// <summary>
        /// This method will find an eligible story to display
        ///
        /// </summary>
        public void showStoryTextLoop()
        {
            if (!errorOnLoad)
            {
            Start: ;

                DateTime temp = DateTime.Now;
                long tempStoryID = -1;

                //try for recent story first
                foreach (Story recent in myStoriesArrayList)
                {
                    if (recent.LastView.CompareTo(temp) < 0)//if earlier than last view then we want it
                    {
                        tempStoryID = recent.StoryID;
                        temp = recent.LastView;
                    }
                }

                //then museum story
                foreach (Story museum in storyManager.GetAdminStoriesArrayList())
                {
                    if (museum.LastView.CompareTo(temp) < 0)//if earlier than last view then we want it
                    {
                        tempStoryID = museum.StoryID;
                        temp = museum.LastView;
                    }
                }

                //if museum and recent stories have already been shown
                for (int i = 0; i < MainMap.Markers.Count; i++)
                {
                    foreach (Story story in storyManager.GetUserStoriesArrayList())
                    {
                        if ((MainMap.Markers[i].Shape as CustomMarkerProjector).storyID == story.StoryID && story.LastView.CompareTo(temp) < 0)//if earlier than last view then we want it
                        {
                            tempStoryID = story.StoryID;
                            temp = story.LastView;
                            break;
                        }
                    }
                }

                //if all stories have been read..
                if (temp.CompareTo(baseTime) > 0)
                {
                    //reset times to before the basetime
                    foreach (Story recent in myStoriesArrayList)
                    {
                        recent.LastView = new DateTime();
                    }
                    foreach (Story museum in storyManager.GetAdminStoriesArrayList())
                    {
                        museum.LastView = new DateTime();
                    }
                    foreach (Story story in storyManager.GetUserStoriesArrayList())
                    {
                        story.LastView = new DateTime();
                    }
                    ReloadStories(true);

                    goto Start;
                }


                if (tempStoryID != -1)//if there is a story to show
                {
                    for (int i = 0; i < MainMap.Markers.Count; i++)
                    {
                        if ((MainMap.Markers[i].Shape as CustomMarkerProjector).storyID == tempStoryID)
                        {
                            (MainMap.Markers[i].Shape as CustomMarkerProjector).ShowMarkerBubble();//show story

                            //set last view on used story
                            foreach (Story recent in myStoriesArrayList)
                            {
                                if (recent.StoryID == tempStoryID)
                                {
                                    recent.LastView = DateTime.Now;
                                    goto End;
                                }
                            }
                            foreach (Story museum in storyManager.GetAdminStoriesArrayList())
                            {
                                if (museum.StoryID == tempStoryID)
                                {
                                    museum.LastView = DateTime.Now;
                                    goto End;
                                }
                            }
                            foreach (Story story in storyManager.GetUserStoriesArrayList())
                            {
                                if (story.StoryID == tempStoryID)
                                {
                                    story.LastView = DateTime.Now;
                                    goto End;
                                }
                            }
                            break;
                        }
                    }
                }
            End: ;
            }
        }

        /// <summary>
        /// fills the random story arraylist with recent stories
        /// </summary>
        private void FillArrayListWithRecentStories()
        {
            storyManager.StoriesArrayList = RemoveDups(storyManager.DownloadRecentStoriesIntoDB(), false);
        }

        //remove duplicate objects
        public ArrayList RemoveDups(ArrayList items, bool allStories)
        {
            ArrayList noDups = new ArrayList();
            foreach (Story story in items)
            {
                bool found = false;
                for (int i = 0; i < noDups.Count; i++)
                {
                    if ((noDups[i] as Story).StoryID == story.StoryID)
                    {
                        found = true;
                        break;
                    }
                }

                if (!allStories)
                {
                    foreach (Story myStory in myStoriesArrayList)
                    {
                        if (story.StoryID == myStory.StoryID)
                        {
                            found = true;
                            break;
                        }
                    }
                }

                if (!found)
                {
                    noDups.Add(story);
                }
            }
            return noDups;
        }

        #endregion

        #region Timers (idle/myStoryLifetime/fetchRecentStories/zoomIn/zoomOut etc...)
        /// <summary>
        /// timer which recycles the displayed stories after a time period has elapsed
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void idleTimer_Tick(object sender, EventArgs e)
        {
            idleTimerRunCount++;
            if (helpDialogueCanvas.Visibility == Visibility.Hidden &&  confirmPositionCanvas.Visibility == Visibility.Hidden 
                && addStoryCatCanvas.Visibility == Visibility.Hidden && addStoryTextCanvas.Visibility == Visibility.Hidden
                && addStoryTimeCanvas.Visibility == Visibility.Hidden && readStoryCanvas.Visibility == Visibility.Hidden && !userIsCurrentlyReadingAStory && !projectorMode)
            {
                //refuses to run on different threads -- that is reason for System.Windows.Forms.Timer
              //  ReloadStories(true);
            }

            if (idleTimerRunCount >= howManyTimesCanIdleTimerRunConsequentlyBeforeResetAppToDefaultState && !projectorMode)
            {
                idleTimerRunCount = 0;
                ResetAppToDefaultState();
            }
        }

        //resets the user stories array once enough time has passed
        //and it is deemed that the user has been inactive for a while
        void myStoryLifetime_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (idleTimerRunCount > 0  || projectorMode)
            {
                myStoryLifetime.Stop();
                myStoryLifetime.Elapsed -= new System.Timers.ElapsedEventHandler(myStoryLifetime_Elapsed);

                //adds the old users stories into the main list before wiping it
                if (myStoriesArrayList.Count > 0)
                {
                    if (!projectorMode)
                    {
                        storyManager.InsertUsersNewStoriesIntoDB(myStoriesArrayList);
                    }

                    if (!currentlyReloadingStories)
                    {
                      myStoriesArrayList = null;
                      myStoriesArrayList = new ArrayList();
                    }

                }

                if (projectorMode)
                {
                    idleTimerRunCount = 0;
                }
            }
        }

        //loads from the DB a list of stories that are new
        void fetchRecentStoriesTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            FetchRecentStories();
        }

        /// <summary>
        /// timer which enables user to hold press on zoom buttons and the zoom level will proceed through the 
        /// levels until either the press is released or the max level is reached.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void zoomOutTimer_Tick(object sender, EventArgs e)
        {
            if (areButtonsBeingUsed)
            {
                MainMap.Zoom = MainMap.Zoom - 0.1;

                zoomTimer.Stop();
                if (zoomTimer.Interval > 100)
                {
                    zoomTimer.Interval -= 100;
                }
                zoomTimer.Start();

                if (MainMap.Zoom == MainMap.MinZoom)
                {
                    zoomTimer.Stop();
                    zoomTimer.Tick -= new EventHandler(zoomOutTimer_Tick);
                }
            }
            else
            {
                zoomTimer.Stop();
                zoomTimer.Tick -= new EventHandler(zoomOutTimer_Tick);
            }
        }

        /// <summary>
        /// timer which enables user to hold press on zoom buttons and the zoom level will proceed through the 
        /// levels until either the press is released or the min level is reached.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void zoomInTimer_Tick(object sender, EventArgs e)
        {
            if (areButtonsBeingUsed)
            {
                MainMap.Zoom = MainMap.Zoom + 0.1;

                zoomTimer.Stop();
                if (zoomTimer.Interval > 100)
                {
                    zoomTimer.Interval -= 100;
                }
                zoomTimer.Start();

                if (MainMap.Zoom == MainMap.MaxZoom)
                {
                    zoomTimer.Stop();
                    zoomTimer.Tick -= new EventHandler(zoomInTimer_Tick);
                }

            }
            else
            {
                zoomTimer.Stop();
                zoomTimer.Tick -= new EventHandler(zoomInTimer_Tick);
            }
        }

        /// <summary>
        /// triggers after user continues to hold a press after touch/mouse down on a filter button
        /// by triggering this timer, the previous states of the buttons are reset back to the values
        /// before the press was performed
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void touchLeaveTimeout_Tick(object sender, EventArgs e)
        {
            if (touchLeaveTimeout.Enabled)
            {
                touchLeaveTimeout.Stop();
                touchLeaveTimeout.Tick -= new EventHandler(touchLeaveTimeout_Tick);


                ////sets back to before changes occured
                //for (int i = 0; i < timeSlotArrayList.Count; i++)
                //{
                //    (timeSlotArrayList[i] as TimeSlot).ShowFilter = (prevTimeSlotArrayList[i] as TimeSlot).ShowFilter;

                //    if ((prevTimeSlotArrayList[i] as TimeSlot).ShowFilter)
                //    {
                //        (timeslotFilterGrid.Children[i] as Image).Opacity = 1;
                //        (timeslotFilterGrid.Children[i] as Image).Source = GetTimeSlotImageByID(false, Convert.ToInt32((timeslotFilterGrid.Children[i] as Image).Tag));
                //    }
                //    else
                //    {
                //        (timeslotFilterGrid.Children[i] as Image).Opacity = 0.99;
                //        (timeslotFilterGrid.Children[i] as Image).Source = GetTimeSlotImageByID(true, Convert.ToInt32((timeslotFilterGrid.Children[i] as Image).Tag));
                //    }
                //}

                for (int i = 0; i < prevTimeSlotArrayList.Count; i++)
                {
                    foreach (TimeSlot timeslot in timeSlotArrayList)
                    {
                        if (timeslot.TimeSlotID == (prevTimeSlotArrayList[i] as TimeSlot).TimeSlotID)
                        {
                            timeslot.ShowFilter = (prevTimeSlotArrayList[i] as TimeSlot).ShowFilter;
                        }
                    }
                    if ((prevTimeSlotArrayList[i] as TimeSlot).ShowFilter)
                    {
                        (timeslotFilterGrid.Children[i] as Image).Opacity = 1;
                        (timeslotFilterGrid.Children[i] as Image).Source = GetTimeSlotImageByID(false, Convert.ToInt32((timeslotFilterGrid.Children[i] as Image).Tag));
                    }
                    else
                    {
                        (timeslotFilterGrid.Children[i] as Image).Opacity = 0.99;
                        (timeslotFilterGrid.Children[i] as Image).Source = GetTimeSlotImageByID(true, Convert.ToInt32((timeslotFilterGrid.Children[i] as Image).Tag));
                    }
                }

                for (int i = 0; i < prevCategoriesArrayList.Count; i++)
                {
                    foreach (Category category in categoriesArrayList)
                    {
                        if (category.CategoryID == (prevCategoriesArrayList[i] as Category).CategoryID)
                        {
                            category.ShowFilter = (prevCategoriesArrayList[i] as Category).ShowFilter;
                            break;
                        }
                    }

                    for (int n = 0; n < categoryFilterGrid.Children.Count; n++)
                    {
                        if ((categoryFilterGrid.Children[n] is Image) && (Convert.ToInt32((categoryFilterGrid.Children[n] as Image).Tag) == (prevCategoriesArrayList[i] as Category).CategoryID))
                        {
                            if ((prevCategoriesArrayList[i] as Category).ShowFilter)
                            {
                                (categoryFilterGrid.Children[n] as Image).Opacity = 1;
                                (categoryFilterGrid.Children[n] as Image).Source = GetCategoryImageByID(true, true, Convert.ToInt32((categoryFilterGrid.Children[n] as Image).Tag));
                            }
                            else
                            {
                                (categoryFilterGrid.Children[n] as Image).Opacity = 0.99;
                                (categoryFilterGrid.Children[n] as Image).Source = GetCategoryImageByID(false, true, Convert.ToInt32((categoryFilterGrid.Children[n] as Image).Tag));
                            }
                            break;
                        }
                    }
                }
                isFilterTouchDown = false;
            }
        }

        #region projector specific timers
        /// <summary>
        /// timer to manage how often the text bubble will display
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void showStoryBubbleTimer_Tick(object sender, EventArgs e)
        {
            if (showStoryBubbleTimer.Enabled)
            {
                showStoryTextLoop();

                showStoryBubbleTimer.Interval = 20000;
                showStoryBubbleTimer.Stop();
            }
        }

        /// <summary>
        /// winforms timer which acts when a the message queue has a new message
        /// and then updates the story list
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void pushNewStoryTimer_Tick(object sender, EventArgs e)
        {
            if (thereIsNewStoryWaitingToBeAdded)
            {
                if (messageReceiveStory != null)
                {
                    //check if size of recent stories is right
                    if (myStoriesArrayList.Count >= MaxNumberMyStoriesToShowAtATime)
                    {
                        myStoriesArrayList.RemoveAt(0);//remove first item,--which has been there the longest
                    }

                    messageReceiveStory.UserStory = true;
                    messageReceiveStory.ShowBubble = true;
                    //messageReceiveStory.LastView = DateTime.Now;
                    myStoriesArrayList.Add(messageReceiveStory); //add new story to the end of the list
                    messageReceiveStory = null;

                    
                    myStoryLifetime.Stop();
                    myStoryLifetime.Elapsed -= new System.Timers.ElapsedEventHandler(myStoryLifetime_Elapsed);//remove any existing timer
                    myStoryLifetime.Elapsed += new System.Timers.ElapsedEventHandler(myStoryLifetime_Elapsed);
                    myStoryLifetime.Interval = 300000; //after 5min of no new stories pushed, other stories will be able to come again
                    myStoryLifetime.Start();
                }

                showStoryBubbleTimer.Interval = 50;
                ReloadStories(false);
                thereIsNewStoryWaitingToBeAdded = false;
                queue.BeginReceive();
            }
        }

        int animTimerCount = 0;
        void manageAnimTimer_Tick(object sender, EventArgs e)
        {
            Random random = new Random();
            double randomNum = random.NextDouble();
            random = null;


            if (randomNum <= 0.2)
            {
                Plane pTemp = new Plane(window.Width, window.Height);
                //container.Children.Add(pTemp);
                grid.Children.Add(pTemp);
            }
            else
            {
                Cloud cTemp = new Cloud(window.Width, window.Height);
                //container.Children.Add(cTemp);
                grid.Children.Add(cTemp);
            }



            if (animTimerCount >= 12)
            {
                for (int i = 0; i < grid.Children.Count; i++)
                {
                    if ((grid.Children[i] is AnimationObject))
                    {
                        if ((grid.Children[i] as AnimationObject).Source == null)
                        {
                            grid.Children.RemoveAt(i);
                            i--;
                        }
                    }
                }
                animTimerCount = 0;
            }
            animTimerCount++;
        }
        #endregion

        #endregion

        #region Message Queuing
        /// <summary>
        /// this method initialises a message queue so that we can
        /// achieve inter-process communication
        /// </summary>
        private bool CreateQueue()
        {
            try
            {
                queue = new MessageQueue(queueName);
                if (projectorMode)
                {
                    queue.ReceiveCompleted += new ReceiveCompletedEventHandler(queue_ReceiveCompleted);
                    queue.BeginReceive();
                }
                return true;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                return false;
            }
        }

        /// <summary>
        /// sends a message to the queue to instruct other processes that an update 
        /// to the database has been made.
        /// </summary>
        private void sendUpdateMessage(Story storyToSendUpdate)
        {
            try
            {
                //Instantiate our MessageContent object.
                MessageContent message = new MessageContent(storyToSendUpdate);

                //Send it to the queue.
                queue.Send(message, "UPDATE");

                //MessageBox.Show("Message sent." + message.CreationDate.Millisecond.ToString(), "MSMQ");
            }
            catch (Exception e)
            {
                Console.WriteLine("Error : Exception on sendUpdateMessage" + e.Message);
            }
        }

        //clear message queue
        private void removeMessages()
        {
            //Purge all messages from the queue.
            try
            {
                queue.Purge();
                Console.WriteLine("Messages purged", "MSMQ");
            }
            catch (Exception e)
            {
                Console.WriteLine("Messages NOT purged", "MSMQ");
                Console.WriteLine(e.Message);
            }
        }

        private void queue_ReceiveCompleted(object sender, ReceiveCompletedEventArgs e)
        {
            if (e.Message.Label.Equals("UPDATE"))
            {
                //lock (sender)
                //{
                // The message is plain text.
                //string text = (string)e.Message.Body;
                Console.WriteLine("Message received");

                try
                {
                    //Set the formatter for the message.
                    e.Message.Formatter = new System.Messaging.XmlMessageFormatter(new Type[1] { typeof(MessageContent) });

                    //Get the MessageContent object out of the message.
                    MessageContent content = (MessageContent)e.Message.Body;

                    messageReceiveStory = content.Story;
                }
                catch (Exception e2)
                {
                    System.Console.WriteLine(e2.ToString() + "There is an ERROR!");
                }
                finally
                {
                    thereIsNewStoryWaitingToBeAdded = true;
                }

                //}
            }
        }
        #endregion

        /// <summary>
        /// Remove current stories and reload another lot
        /// </summary>
        /// <param name="filterAndRandomize">if true, stories loaded to map will be totally random set
        /// and according to the filters etc. if false, stories loaded will use just whatever the results
        /// of the last query was. That would be useful for example on first app launch, the local array in
        /// storymanager is filled with random stories anyway so no need to re-query, just fetch what was loaded in</param>
        bool currentlyReloadingStories = false; //attempt at some thread safety
        private void ReloadStories(bool filterAndRandomize)
        {
            if (!errorOnLoad && ((!currentlyReloadingStories && readMode) || (!currentlyReloadingStories && welcomeActive) || (!currentlyReloadingStories && projectorMode)))
            {
                currentlyReloadingStories = true;
                if (MainMap.Markers.Count > 0)
                {
                    MainMap.Markers.Clear();//clear all previous markers from the map
                }

                bool catConsistant = false;
                bool timeConsistant = false;

                if (!projectorMode)
                {
                    bool catValue = false; //off
                    bool timeValue = false; //off

                    for (int i = 0; i < categoriesArrayList.Count; i++)
                    {
                        if (i == 0)
                        {
                            if (!(categoriesArrayList[i] as Category).ShowFilter) //if hidden
                            {
                                catValue = false;
                                catConsistant = true;
                            }
                            else //if showing
                            {
                                catValue = true;
                                catConsistant = true;
                            }
                        }
                        else
                        {
                            if (!(categoriesArrayList[i] as Category).ShowFilter) //if hidden
                            {
                                if (catValue)
                                {
                                    catConsistant = false;
                                    break;
                                }
                            }
                            else //if showing
                            {
                                if (!catValue)
                                {
                                    catConsistant = false;
                                    break;
                                }
                            }
                        }
                    }

                    for (int i = 0; i < timeSlotArrayList.Count; i++)
                    {
                        if (i == 0)
                        {
                            if (!(timeSlotArrayList[i] as TimeSlot).ShowFilter) //if hidden
                            {
                                timeValue = false;
                                timeConsistant = true;
                            }
                            else //if showing
                            {
                                timeValue = true;
                                timeConsistant = true;
                            }
                        }
                        else
                        {
                            if (!(timeSlotArrayList[i] as TimeSlot).ShowFilter) //if hidden
                            {
                                if (timeValue)
                                {
                                    timeConsistant = false;
                                    break;
                                }
                            }
                            else //if showing
                            {
                                if (!timeValue)
                                {
                                    timeConsistant = false;
                                    break;
                                }
                            }
                        }
                    }
                }
                else
                {
                    timeConsistant = true;
                    catConsistant = true;
                }


                ArrayList tempStories = new ArrayList();
                if (filterAndRandomize)
                {
                    tempStories.AddRange(storyManager.GetRandomFilteredAdminStories(false, MainMap.CurrentViewArea, catConsistant, timeConsistant));
                    if (!projectorMode)
                    {
                        tempStories.AddRange(storyManager.GetRandomFilteredUserStories(false, MainMap.CurrentViewArea, catConsistant, timeConsistant));
                    }
                }
                else
                {
                    tempStories.AddRange(storyManager.GetAdminStoriesArrayList());
                    if (!projectorMode)
                    {
                        tempStories.AddRange(storyManager.GetUserStoriesArrayList());
                    }
                }


                if(!myStoryLifetime.Enabled)
                {
                    myStoriesArrayList = null;
                    myStoriesArrayList = new ArrayList();
                }

                int index = 0;
                foreach (Story story in myStoriesArrayList)
                {
                    //removes any stories that are over the specfied limit of user stories to show
                    if (myStoriesArrayList.Count > MaxNumberMyStoriesToShowAtATime)
                    {
                        if (myStoriesArrayList.Count - MaxNumberMyStoriesToShowAtATime <= index)
                        {
                            story.UserStory = true; //indicate that this story is special
                            tempStories.Add(story); //add the user stories to the list about to be added to the map
                        }
                        index++;
                    }
                    else
                    {
                        story.UserStory = true; //indicate that this story is special
                        tempStories.Add(story); //add the user stories to the list about to be added to the map
                    }
                }

                int recentCount = 0;//number of recent stories
                ArrayList tempRecent = null;
                //adds recent user stories if there is room in the arraylist
                if (projectorMode && myStoriesArrayList.Count < MaxNumberMyStoriesToShowAtATime)
                {
                    FillArrayListWithRecentStories();
                    Random rInt = new Random();
                    tempRecent = (ArrayList)storyManager.StoriesArrayList.Clone();

                    foreach (Story story in myStoriesArrayList)
                    {
                        for (int o = 0; o < tempRecent.Count; o++)
                        {
                            if (story.StoryID == (tempRecent[o] as Story).StoryID)
                            {
                                tempRecent.RemoveAt(o);
                            }
                        }
                    }

                    int numRecentStories = MaxNumberMyStoriesToShowAtATime - myStoriesArrayList.Count;
                    for (int i = 0; i < tempRecent.Count; i++)
                    {
                        if (i < numRecentStories)
                        {
                            int randInt = rInt.Next(0, tempRecent.Count);
                            //add recent stories to top up the list to show on the map
                            tempStories.Add(tempRecent[randInt]);
                            tempRecent.RemoveAt(randInt);
                            i--;
                            recentCount++;
                        }
                        else
                        {
                            break;
                        }
                    }
                    tempRecent = null;
                }

                if (projectorMode && (myStoriesArrayList.Count + recentCount) < MaxNumberMyStoriesToShowAtATime)
                {
                    int numRandomStories = MaxNumberMyStoriesToShowAtATime - (myStoriesArrayList.Count + recentCount);

                    //if there are not enough recent stories
                    ArrayList temp = (ArrayList)storyManager.StoriesArrayList.Clone(); //backup any recent stories
                    storyManager.GetRandomFilteredUserStories(false);
                    tempRecent = (ArrayList)storyManager.StoriesArrayList.Clone();

                    foreach (Story story in myStoriesArrayList)
                    {
                        //remove duplicated mystories as recent stories
                        for (int o = 0; o < tempRecent.Count; o++)
                        {
                            if (story.StoryID == (tempRecent[o] as Story).StoryID)
                            {
                                tempRecent.RemoveAt(o);
                                o--;
                            }
                        }
                    }


                    storyManager.StoriesArrayList = new ArrayList();
                    storyManager.StoriesArrayList.AddRange(tempRecent);
                    tempRecent = null;
                    

                    for (int i = 0; i < storyManager.GetUserStoriesArrayList().Count; i++)
                    {
                        if (i < numRandomStories)
                        {
                            //add random stories to top up the list to show on the map
                            tempStories.Add(storyManager.GetUserStoriesArrayList()[i]);
                        }
                        else
                        {
                            break;
                        }
                    }

                    storyManager.StoriesArrayList.AddRange(temp);
                    temp = null;
                }

                //sorts the story arraylist so that they are added to the map in the correct order(no bad overlaps)
                tempStories = RemoveDups(tempStories, true);
                storyManager.sortStoryArrayList(tempStories);
                foreach (Story story in tempStories)
                {
                    if (filterAndRandomize) //do animation on reload marker
                    {
                        addMarkerToMap(story.StoryLatLng, story.StoryContent, story.Title, story.CategoryID, story.ShowBubble, story.StoryID, story.TimeSlotID, story.UserStory, story.museumImgURL, true);
                    }
                    else //no anim
                    {
                        addMarkerToMap(story.StoryLatLng, story.StoryContent, story.Title, story.CategoryID, story.ShowBubble, story.StoryID, story.TimeSlotID, story.UserStory, story.museumImgURL, false);
                    }
                    story.ShowBubble = false;
                }

                currentlyReloadingStories = false;
            }
            else if (projectorMode)
            {
                //worst case  make a timer to restore app functions after a while to ensure application longevity
                Console.WriteLine("Reload Conflict!");

                //defer these for a short time
                System.Windows.Forms.Timer restartProjApp = new System.Windows.Forms.Timer();
                restartProjApp.Interval = 30000;
                restartProjApp.Tick += new EventHandler(restartProjApp_Tick);
                restartProjApp.Start();
            }
        }

        void restartProjApp_Tick(object sender, EventArgs e)
        {
            if (sender != null)
            {
                (sender as System.Windows.Forms.Timer).Stop();
                (sender as System.Windows.Forms.Timer).Tick -= new EventHandler(restartProjApp_Tick);
                sender = null;
            }

            currentlyReloadingStories = false;
            myStoriesArrayList.Clear();
            ReloadStories(true);
        }

        /// <summary>
        /// Resets all the filter options
        /// makes them selected again
        /// </summary>
        private void ResetAllFiltersToSelected()
        {
            bool catRefreshRequired = false;
            bool timeRefreshRequired = false;

            int index = 0;
            foreach (Category cat in categoriesArrayList)
            {
                if (!cat.ShowFilter)
                {
                    for (int n = 0; n < categoryFilterGrid.Children.Count; n++)
                    {
                        if ((categoryFilterGrid.Children[n] is Image) && (Convert.ToInt32((categoryFilterGrid.Children[n] as Image).Tag) == cat.CategoryID))
                        {
                            cat.ShowFilter = true;
                            catRefreshRequired = true;
                            (categoryFilterGrid.Children[n] as Image).Opacity = 1;
                            (categoryFilterGrid.Children[n] as Image).Source = cat.CatImgUNSelectedInputBox;
                            break;
                        }
                    }
                }
                index++;
            }

            index = 0;
            foreach (TimeSlot time in timeSlotArrayList)
            {
                if (!time.ShowFilter)
                {
                    time.ShowFilter = true;
                    timeRefreshRequired = true;
                    (timeslotFilterGrid.Children[index] as Image).Opacity = 1;
                    (timeslotFilterGrid.Children[index] as Image).Source = time.TimeSlotImgUnSelected;
                }
                index++;
            }

            //sync the filter status of the cat&timeslots in db with the arraylists
            if (catRefreshRequired)
            {
                storyManager.UpdateAllCategoryFilterStatus(categoriesArrayList, false);
            }
            if (timeRefreshRequired)
            {
                storyManager.UpdateAllTimeSlotFilterStatus(timeSlotArrayList, false);
            }
            //update the view of the stories (since filters status reset)
            if (catRefreshRequired || timeRefreshRequired)
            {
                ReloadStories(true);
            }
        }

        /// <summary>
        /// Checks if cat/time slots are selected & there is some content typed
        /// in story input area.
        /// </summary>
        /// <param name="showErrorArea">if true, show Visual Feedback (animation over area)</param>
        /// <returns>true if everything is valid, false if cannot submit story</returns>
        private bool VerifyIfStoryCanBeSubmitted(bool showErrorArea)
        {
            if (showErrorArea)
            {
                if (!(storyInputTextBox.Text.Length > 0))
                {
                    //pulse over the input area
                    pulseOverStory.Visibility = System.Windows.Visibility.Visible;
                    Storyboard fade = (Storyboard)Resources["StoryInputFadeInThenOut"];
                    fade.Begin();
                    //showGrowlNotification(newStoryValidation, newStoryValidationTitle, newStoryTextNotTypedNotification);
                }

                if (!aCategoryHasBeenSelected)
                {
                    pulseOverCategories.Visibility = System.Windows.Visibility.Visible;
                    Storyboard fade = (Storyboard)Resources["CategoryInputFadeInThenOut"];
                    fade.Begin();
                    //showGrowlNotification(newStoryValidation, newStoryValidationTitle, newStoryCategoryNotSelectedNotification);
                }

                if (!aTimeSlotHasBeenSelected)
                {
                    pulseOverTimeSlot.Visibility = System.Windows.Visibility.Visible;
                    Storyboard fade = (Storyboard)Resources["TimeSlotInputFadeInThenOut"];
                    fade.Begin();
                    //showGrowlNotification(newStoryValidation, newStoryValidationTitle, newStoryTimeNotSelectedNotification);
                }
            }

            if (storyInputTextBox.Text.Length > 0 && aCategoryHasBeenSelected && aTimeSlotHasBeenSelected)
            {
                shareStoryImgBtn.Opacity = 1;
                return true;
            }
            else
            {
                shareStoryImgBtn.Opacity = 0.5;
                return false;
            }
        }

        /// <summary>
        /// Set up the input canvas to take input from the user when they have dropped something onto the map
        /// </summary>
        private void InputStory()
        {
            //only proceed if a story is not already being entered
            if (storyInputCanvas.Visibility == System.Windows.Visibility.Hidden)
            {
                shouldReloadOnTouch = false;

                currentlySelectedCat.Source = null;
                //make the input prompt visible
                storyInputCanvas.Visibility = System.Windows.Visibility.Visible;

                //plus the rectangle behind it
                blackRectangleCanvas.Visibility = System.Windows.Visibility.Visible;
                blackRectangleCanvas.Opacity = 0;
                blackRectangleCanvas.Height = window.Height;
                blackRectangleCanvas.Width = window.Width;
                Storyboard fadeInRect = (Storyboard)Resources["blackRectCanvasFadeIn"];
                fadeInRect.Begin();

                storyInputCanvas.Opacity = 0;

                if (portraitScreen)//adjust story input appearence if on portrait
                {
                    storyInputCanvas.Margin = new Thickness(storyInputCanvas.Margin.Left, 142,
                        storyInputCanvas.Margin.Right, storyInputCanvas.Margin.Bottom);
                }

                int yTranslate = Convert.ToInt32((storyInputCanvas.Height + storyInputCanvas.Margin.Top) - (MainMap.Height / 2));
                int xTranslate = Convert.ToInt32((MainMap.Width / 2) - ((MainMap.Width - storyInputCanvas.Width) / 2) - 88);

                GPoint localPoint = MainMap.FromLatLngToLocal(currentPosition);
                localPoint = new GPoint(localPoint.X + xTranslate, localPoint.Y - yTranslate);
                PointLatLng gmapPoint = MainMap.FromLocalToLatLng(localPoint.X, localPoint.Y);

                //MainMap.Position = gmapPoint;
                if (panTo(gmapPoint, true, 0))// moves the map center to the position with a smooth pan
                {
                    reloadAfterPan = true;
                }

                Storyboard fadeIn = (Storyboard)Resources["StoryCanvasFadeIn"];
                fadeIn.Begin();
                storyTitleInputTextBox.Focus();

                //storyInputTextBox.Text += "Address : " + MainMap.Manager.GetPlacemarkFromGeocoder(currentPosition).Address;
                //storyInputTextBox.Text += "\n Locality Name : " + MainMap.Manager.GetPlacemarkFromGeocoder(currentPosition).LocalityName;
                //storyInputTextBox.Text += "\n Sub Administrative AreaName : " + MainMap.Manager.GetPlacemarkFromGeocoder(currentPosition).SubAdministrativeAreaName;
                //storyInputTextBox.Text += "\n CountryNameCode & Country Name : " + MainMap.Manager.GetPlacemarkFromGeocoder(currentPosition).CountryNameCode + " , " + MainMap.Manager.GetPlacemarkFromGeocoder(currentPosition).CountryName;
                //storyInputTextBox.Text += "\n Postal Code # : " + MainMap.Manager.GetPlacemarkFromGeocoder(currentPosition).PostalCodeNumber;

                ShowKeyboard();
            }
        }

        /// <summary>
        /// Set up the input canvas to take input from the user when they have dropped something onto the map
        /// </summary>
        private void NewInputStory(bool goneBack)
        {
            //only proceed if a story is not already being entered
            if (addStoryTimeCanvas.Visibility == System.Windows.Visibility.Hidden)
            {
                shouldReloadOnTouch = false;

                if (!goneBack) //means this is direct from dragging pin
                //NOT used back button from next input page
                {
                    //make the faded background visible
                    blackRectangleCanvas.Visibility = Visibility.Visible;
                    blackRectangleCanvas.Opacity = 0;
                    blackRectangleCanvas.Height = window.Height;
                    blackRectangleCanvas.Width = window.Width;
                    Storyboard fadeInRect = (Storyboard)Resources["blackRectCanvasDarkFadeIn"];
                    fadeInRect.Begin();
                }


                //hide text canvas if the back button was used
                if (addStoryTextCanvas.Visibility == System.Windows.Visibility.Visible)
                {
                    Storyboard fadeOut = (Storyboard)Resources["StoryCanvasTextFadeOut"];
                    fadeOut.Begin();
                }

                //make the input prompt visible
                addStoryTimeCanvas.Visibility = Visibility.Visible;
                addStoryTimeCanvas.Opacity = 0;

                if (portraitScreen)//adjust story input appearance if on portrait
                {
                    addStoryTimeCanvas.Margin = new Thickness(addStoryTimeCanvas.Margin.Left, 142,
                        addStoryTimeCanvas.Margin.Right, addStoryTimeCanvas.Margin.Bottom);
                }

                Storyboard fadeIn = (Storyboard)Resources["StoryCanvasTimeFadeIn"];
                fadeIn.Begin();


            }
        }

        /// <summary>
        /// Set up the input canvas to take input from the user when they have dropped something onto the map
        /// </summary>
        private void InputStoryText()
        {
            //make the input prompt visible and hide previous screen
            Storyboard fadeOut;
            if (addStoryTimeCanvas.Visibility == System.Windows.Visibility.Visible)
            {
                fadeOut = (Storyboard)Resources["StoryCanvasTimeFadeOut"];
                fadeOut.Begin();
            }
            else if (addStoryCatCanvas.Visibility == System.Windows.Visibility.Visible)
            {
                fadeOut = (Storyboard)Resources["StoryCanvasCatFadeOut"];
                fadeOut.Begin();
            }
            //addStoryTimeCanvas.Visibility = Visibility.Hidden;
            addStoryTextCanvas.Visibility = Visibility.Visible;
            addStoryTextCanvas.Opacity = 0;

            if (portraitScreen)//adjust story input appearance if on portrait
            {
                addStoryTextCanvas.Margin = new Thickness(addStoryTextCanvas.Margin.Left, 142,
                    addStoryTextCanvas.Margin.Right, addStoryTextCanvas.Margin.Bottom);
            }

            Storyboard fadeIn = (Storyboard)Resources["StoryCanvasTextFadeIn"];
            fadeIn.Begin();

            ShowKeyboard();
        }

        /// <summary>
        /// Set up the input canvas to take input from the user when they have dropped something onto the map
        /// </summary>
        private void InputStoryCategory()
        {
            //make the input prompt visible and hide previous screen
            Storyboard fadeOut;
            if (addStoryTextCanvas.Visibility == System.Windows.Visibility.Visible)
            {
                fadeOut = (Storyboard)Resources["StoryCanvasTextFadeOut"];
                fadeOut.Begin();
            }
            else if (nearlyThereCanvas.Visibility == System.Windows.Visibility.Visible)
            {
                fadeOut = (Storyboard)Resources["StoryCanvasNearlyThereFadeOut"];
                fadeOut.Begin();
            }
            //addStoryTextCanvas.Visibility = Visibility.Hidden;
            addStoryCatCanvas.Visibility = Visibility.Visible;
            addStoryCatCanvas.Opacity = 0;

            if (portraitScreen)//adjust story input appearance if on portrait
            {
                addStoryCatCanvas.Margin = new Thickness(addStoryCatCanvas.Margin.Left, 142,
                    addStoryCatCanvas.Margin.Right, addStoryCatCanvas.Margin.Bottom);
            }

            Storyboard fadeIn = (Storyboard)Resources["StoryCanvasCatFadeIn"];
            fadeIn.Begin();
        }

        /// <summary>
        /// Set up
        /// </summary>
        private void InputStoryNearlyThere()
        {
            //make the input prompt visible and hide previous screen
            if (addStoryCatCanvas.Visibility == System.Windows.Visibility.Visible)
            {
                Storyboard fadeOut = (Storyboard)Resources["StoryCanvasCatFadeOut"];
                fadeOut.Begin();
            }
            //addStoryTextCanvas.Visibility = Visibility.Hidden;
            nearlyThereCanvas.Visibility = Visibility.Visible;
            nearlyThereCanvas.Opacity = 0;

            if (portraitScreen)//adjust story input appearance if on portrait
            {
                nearlyThereCanvas.Margin = new Thickness(nearlyThereCanvas.Margin.Left, 142,
                    nearlyThereCanvas.Margin.Right, nearlyThereCanvas.Margin.Bottom);
            }

            Storyboard fadeIn = (Storyboard)Resources["StoryCanvasNearlyThereFadeIn"];
            fadeIn.Begin();
        }

        /// <summary>
        /// Removes characters we dont want like ' and &,
        /// replaces them with appropriate replacements
        /// </summary>
        /// <param name="p">the string to filter</param>
        /// <returns>filtered string</returns>
        static string FilterTheStoryFromBadChars(string p)
        {
            StringBuilder b = new StringBuilder(p);
            b.Replace("  ", string.Empty);
            b.Replace(Environment.NewLine, string.Empty);
            b.Replace("\'", "`");
            b.Replace("&", "§");
            b.Replace(";", ":");
            return b.ToString();
        }

        /// <summary>
        /// Closes the input area which includes:
        /// * Close the Keyboard
        /// * fade out & hide the faded black background at input area
        /// * fade out & hide the story input canvas
        /// * reset selection states of input category/timeline
        /// </summary>
        private void CloseStoryInput(bool doNotCloseBlackCanvas)
        {
            Storyboard fadeOut;
            if (addStoryTimeCanvas.Visibility == System.Windows.Visibility.Visible)
            {
                fadeOut = (Storyboard)Resources["StoryCanvasTimeFadeOut"];
                fadeOut.Begin();
            }
            else if (addStoryTextCanvas.Visibility == System.Windows.Visibility.Visible)
            {
                fadeOut = (Storyboard)Resources["StoryCanvasTextFadeOut"];
                fadeOut.Begin();
                CloseKeyboard();
            }
            else if (addStoryCatCanvas.Visibility == System.Windows.Visibility.Visible)
            {
                fadeOut = (Storyboard)Resources["StoryCanvasCatFadeOut"];
                fadeOut.Begin();
            }
            else if (nearlyThereCanvas.Visibility == System.Windows.Visibility.Visible)
            {
                fadeOut = (Storyboard)Resources["StoryCanvasNearlyThereFadeOut"];
                fadeOut.Begin();
            }

            //if (whiteRectangleCanvas.Visibility != Visibility.Visible) //if closing thankyou with read mode
            //{
            //    label_thankyouforsharing.Visibility = System.Windows.Visibility.Hidden;
            //    label_thankyouforsharing2.Visibility = System.Windows.Visibility.Hidden;
            //    button_addstory.Visibility = System.Windows.Visibility.Hidden;
            //    button_readstory.Visibility = System.Windows.Visibility.Hidden;

            //    if (readMode)
            //    {
            //        ReadStoryMode();
            //    }
            //}

            if (!doNotCloseBlackCanvas)
            {
                Storyboard rectfadeOut = (Storyboard)Resources["blackRectCanvasFadeOut"];
                rectfadeOut.Begin();
            }

            resetStateofPreviouslySelectedCategoryImg_ForInputBox();
            resetStateofPreviouslySelectedTimeSlotImg();
            storyInputTextBox.Text = "";
            storyTitleInputTextBox.Text = "";
            shouldReloadOnTouch = true;
            idleTimer.Start();
            idleTimerRunCount = 0;
        }

        /// <summary>
        /// Place the WPF On Screen Keyboard in the right place and make it visible
        /// </summary>
        private void ShowKeyboard()
        {
            if (floatingTouchScreenKeyboard1.IsOpen == false)
            {
                floatingTouchScreenKeyboard1.VerticalOffset = MainMap.Height - floatingTouchScreenKeyboard1.Height - 300;
                floatingTouchScreenKeyboard1.HorizontalOffset = 0;
                floatingTouchScreenKeyboard1.IsOpen = true;
            }
        }
        /// <summary>
        /// Close the keyboard
        /// </summary>
        private void CloseKeyboard()
        {
            if (floatingTouchScreenKeyboard1.IsOpen == true)
            {
                floatingTouchScreenKeyboard1.IsOpen = false;
            }
        }

        private void storyCanvasFadeIn_Completed(object sender, EventArgs e)
        {
            if (addStoryTextCanvas.Visibility == System.Windows.Visibility.Visible)
            {
                storyTitleInputTextBox.Focus();
            }
        }

        private void storyInputTextBox_TouchUp(object sender, TouchEventArgs e)
        {
            sendF1();
        }

        private void sendF1()
        {
            KeyPress(System.Windows.Forms.Keys.F1);
        }

        #region touch/gesture stuff
        int firstTouchId = -1;
        Point firstTimeTouch1 = new Point();
        Point firstTimeTouch2 = new Point();
        Point movingTouch1 = new Point();
        Point movingTouch2 = new Point();
        int countNumTouches = 0;
        bool centeredToCenterPoint = false;
        bool usedZoom = false;
        PointLatLng touchCenterLatLng;
        double pinchZoomIncrementValue = 0.06; //adjusts pinch zoom sensitivity!
        double lastTouchDistance = 0;
        /// <summary>
        /// For debugging
        /// </summary>
        /// <param name="centerX"></param>
        /// <param name="centerY"></param>
        private void ShowTouchPositionLabels()
        {
            //lblONE.Margin = new Thickness(movingTouch1.X - (lblONE.Width / 2), movingTouch1.Y - (lblONE.Height / 2), 0, 0);
            //lblTWO.Margin = new Thickness(movingTouch2.X - (lblTWO.Width / 2), movingTouch2.Y - (lblTWO.Height / 2), 0, 0);
            //lblCENTER.Margin = new Thickness(movingCenterX - (lblCENTER.Width / 2), movingCenterY - (lblCENTER.Height / 2), 0, 0);
            if (lblONE.Visibility != System.Windows.Visibility.Visible)
            {
                lblONE.Visibility = System.Windows.Visibility.Visible;
            }
            if (lblTWO.Visibility != System.Windows.Visibility.Visible)
            {
                lblTWO.Visibility = System.Windows.Visibility.Visible;
            }
            if (lblCENTER.Visibility != System.Windows.Visibility.Visible)
            {
                lblCENTER.Visibility = System.Windows.Visibility.Visible;
            }
            lblONE.Margin = new Thickness(movingTouch1.X - 24.5, movingTouch1.Y - 49.5, 0, 0);
            lblTWO.Margin = new Thickness(movingTouch2.X - 24.5, movingTouch2.Y - 49.5, 0, 0);
            double centerX = (movingTouch1.X + movingTouch2.X) / 2;
            double centerY = (movingTouch1.Y + movingTouch2.Y) / 2;
            lblCENTER.Margin = new Thickness(centerX - 24.5, centerY - 49.5, 0, 0);
        }

        /// <summary>
        /// See if there is difference between 2 values (to know if should react to the touch)
        /// </summary>
        /// <param name="delta1">value 1</param>
        /// <param name="delta2">value 2</param>
        /// <param name="sensitivity">Checks if thers difference greater than this value between 2 points, help control sensitivity</param>
        /// <returns></returns>
        private bool isDeltaDifference(double delta1, double delta2, int sensitivity)
        {
            if (((delta1 - delta2) > sensitivity) || ((delta2 - delta1) > sensitivity))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private void MainMap_TouchDown(object sender, TouchEventArgs e)
        {
            if (countNumTouches < 2)
            {
                TouchPoint tp = e.GetTouchPoint(MainMap);
                if (firstTouchId == -1)
                {
                    firstTouchId = e.TouchDevice.Id;
                    firstTimeTouch1.X = tp.Position.X;
                    firstTimeTouch1.Y = tp.Position.Y;
                }
                else
                {
                    firstTimeTouch2.X = tp.Position.X;
                    firstTimeTouch2.Y = tp.Position.Y;
                }
                countNumTouches++;
            }

            if (countNumTouches == 2)
            {
                double dx = firstTimeTouch1.X - firstTimeTouch2.X;
                double dy = firstTimeTouch1.Y - firstTimeTouch2.Y;
                lastTouchDistance = Math.Sqrt(dx * dx + dy * dy);

                double centerX = (firstTimeTouch1.X + firstTimeTouch2.X) / 2;
                double centerY = (firstTimeTouch1.Y + firstTimeTouch2.Y) / 2;
                touchCenterLatLng = (MainMap.FromLocalToLatLng((int)centerX, (int)centerY));
                centeredToCenterPoint = false;

                if (!touchedMarker)//if this touch is not done on a marker
                {
                    MainMap.DragButton = MouseButton.Right;
                }
                touchedMarker = false;
            }
            else
            {
                if (!touchedMarker)//if this touch is not done on a marker
                {
                    MainMap.DragButton = MouseButton.Left;
                }
                touchedMarker = false;
            }
        }


        private void MainMap_TouchLeave(object sender, TouchEventArgs e)
        {
            if (e.TouchDevice.Id == firstTouchId)
            {
                firstTouchId = -1;
                firstTimeTouch1.X = 0;
                firstTimeTouch1.Y = 0;
                movingTouch1.X = 0;
                movingTouch1.Y = 0;
            }
            else
            {
                firstTimeTouch2.X = 0;
                firstTimeTouch2.Y = 0;
                movingTouch2.X = 0;
            }
            lastTouchDistance = 0;
            if (countNumTouches > 0)
            {
                countNumTouches--;
            }

            if (countNumTouches > 1)
            {
                if (!touchedMarker)//if this touch is not done on a marker
                {
                    MainMap.DragButton = MouseButton.Right;
                }
                touchedMarker = false;
            }
            else
            {
                if (!touchedMarker)//if this touch is not done on a marker
                {
                    MainMap.DragButton = MouseButton.Left;
                }
                touchedMarker = false;
            }
        }

        private void MainMap_TouchMove(object sender, TouchEventArgs e)
        {
            if (countNumTouches == 2)
            {
                TouchPoint tp = e.GetTouchPoint(window);
                if (e.TouchDevice.Id == firstTouchId)
                {
                    movingTouch1.X = tp.Position.X;
                    movingTouch1.Y = tp.Position.Y;
                }
                else if (e.TouchDevice.Id != firstTouchId)
                {
                    movingTouch2.X = tp.Position.X;
                    movingTouch2.Y = tp.Position.Y;
                }

                double dx = movingTouch1.X - movingTouch2.X;
                double dy = movingTouch1.Y - movingTouch2.Y;
                double touchDistance = Math.Sqrt(dx * dx + dy * dy);
                //ShowTouchPositionLabels();
                if (isDeltaDifference(touchDistance, lastTouchDistance, 2)) //if theres enough difference between them
                {
                    double zoomRatio = touchDistance / lastTouchDistance;
                    if (zoomRatio > 1)
                    {
                        if (!centeredToCenterPoint)
                        {
                            MainMap.Position = touchCenterLatLng;
                            centeredToCenterPoint = true;
                        }
                        if (MainMap.Zoom + pinchZoomIncrementValue <= MainMap.MaxZoom - 0.01)
                        {
                            MainMap.Zoom += pinchZoomIncrementValue;
                        }
                        else
                        {
                            MainMap.Zoom = MainMap.MaxZoom;
                        }
                    }
                    else if (zoomRatio < 1)
                    {
                        if (MainMap.Zoom - pinchZoomIncrementValue < MainMap.MinZoom + 0.05)
                        {
                            MainMap.Zoom = MainMap.MinZoom + 0.05;
                        }
                        else
                        {
                            MainMap.Zoom -= pinchZoomIncrementValue;
                        }
                    }
                    usedZoom = true;
                    lastTouchDistance = touchDistance;
                }
            }
            ////check if the MainMap.Position is within the area
            //if (auckBoundRect.Contains(MainMap.Position))
            //{
            //    //Console.Write("You are dragging within the bounds");
            //}
            //else
            //{
            //    //Console.Write("You are dragging OUTSIDE the bounds");
            //    MainMap.Position = mapCenterPosition;

            //    //panTo(mapCenterPosition, false);
            //}
            #region a laggy/bad way to do the above
            //bool needsRepositioning = false;
            //PointLatLng newPosition = new PointLatLng(MainMap.Position.Lat, MainMap.Position.Lng);
            //if (MainMap.Position.Lat > scrollBoundTopLat)
            //{
            //    newPosition.Lat = scrollBoundTopLat;
            //    needsRepositioning = true;
            //}
            //if (MainMap.Position.Lat < scrollBoundBottomLat)
            //{
            //    newPosition.Lat = scrollBoundBottomLat;
            //    needsRepositioning = true;
            //}
            //if (MainMap.Position.Lng < scrollBoundLeftLng)
            //{
            //    newPosition.Lng = scrollBoundLeftLng;
            //    needsRepositioning = true;
            //}
            //if (MainMap.Position.Lng > scrollBoundRightLng)
            //{
            //    newPosition.Lng = scrollBoundRightLng;
            //    needsRepositioning = true;
            //}
            //if (needsRepositioning)
            //{
            //    MainMap.Position = newPosition;
            //}
            #endregion
        }


        private void MainMap_TouchUp(object sender, TouchEventArgs e)
        {
            if (usedZoom)//if touch is done and zoom is off
            {
                usedZoom = false;
                MainMap.Zoom = Math.Round(MainMap.Zoom, MidpointRounding.AwayFromZero);
            }
        }

        #endregion


        Point initialTouchLocation = new Point(-1, -1);
        private void blackRectangleCanvas_MouseMove(object sender, MouseEventArgs e)
        {
            //if moving with the button pressed (or just dragging single finger)
            if ((e.RightButton == MouseButtonState.Pressed || e.LeftButton == MouseButtonState.Pressed) && initialTouchLocation != new Point(-1, -1))
            {
                Point currentTouchLocation = this.PointToScreen(Mouse.GetPosition(window));
                double dx = initialTouchLocation.X - currentTouchLocation.X;
                double dy = initialTouchLocation.Y - currentTouchLocation.Y;
                double touchDistance = Math.Sqrt(dx * dx + dy * dy);
                //Console.WriteLine("touch distance = " + touchDistance.ToString());
                if (touchDistance > 200)
                {
                    //if (welcomeActive && !initialWelcomeScreen)
                    //{
                    //    displayWelcomeScreen();
                    //    if (welcomeSwitchTimer == null)
                    //    {
                    //        welcomeSwitchTimer.Stop();
                    //        welcomeSwitchTimer.Start();
                    //    }
                    //}

                    //else
                    //{
                        if (button_addstory.Visibility != System.Windows.Visibility.Hidden) //if on thankyou story screen
                        {
                            readMode = true;
                            CloseStoryInput(false);
                        }
                        else
                        {
                            //check this call soon too... its definately being fired more than once, unncessarily
                            HideReadStoryCanvas();
                            CloseStoryInput(false);
                            fadeOutHelpCanvas(false);
                            fadeOutTermsCanvas();
                            HideConfirmPositionCanvas();
                        }

                        if (storyJustSubmitted)
                        {
                            storyJustSubmitted = false;
                            ReloadStories(true);
                        }
                    //}

                    
                    //comment this out for now, not too thread safe!
                    //showGrowlNotification(errorNotification, storyInputCancelledTitle, storyInputCancelledNotification);
                }
            }
        }

        private void blackRectangleCanvas_MouseUp(object sender, MouseButtonEventArgs e)
        {
            initialTouchLocation = new Point(-1, -1);
        }

        private void blackRectangleCanvas_MouseDown(object sender, MouseButtonEventArgs e)
        {
            initialTouchLocation = this.PointToScreen(Mouse.GetPosition(window));
        }

        private void newStoryButton_MouseUp(object sender, MouseButtonEventArgs e)
        {
            ShowGrowlNotification(errorNotification, storyCreationFailedToDragTheIconTitle, storyCreationFailedToDragTheIconNotification);
        }

        private void ShowGrowlNotification(NotificationType notificationTypeToUse, string title, string notificationText)
        {
            if (GrowlConnector.IsGrowlRunningLocally())
            {
                Notification notification = new Notification(this.application.Name, notificationTypeToUse.Name, null, title, notificationText);
                notification.Icon = notificationTypeToUse.Icon;
                this.growl.Notify(notification);
            }
        }

        private void filterBackground_MouseDown(object sender, MouseButtonEventArgs e)
        {
            idleTimer.Stop();
            mouseDown = true;
            isFilterTouchDown = !isFilterTouchDown;

            prevCategoriesArrayList = new ArrayList();
            foreach (Category category in categoriesArrayList)
            {
                for (int i = 0; i < categoryFilterGrid.Children.Count; i++)
                {
                    if (categoryFilterGrid.Children[i] is Image)
                    {
                        if (Convert.ToInt32((categoryFilterGrid.Children[i] as Image).Tag) == category.CategoryID)
                        {
                            Category temp;
                            temp = (Category)category.Clone();
                            prevCategoriesArrayList.Add(temp);
                            break;
                        }
                    }
                }
            }

            prevTimeSlotArrayList = new ArrayList();
            foreach (TimeSlot timeslot in timeSlotArrayList)
            {
                for (int i = 0; i < timeslotFilterGrid.Children.Count; i++)
                {
                    if (Convert.ToInt32((timeslotFilterGrid.Children[i] as Image).Tag) == timeslot.TimeSlotID)
                    {
                        TimeSlot temp;
                        temp = (TimeSlot)timeslot.Clone();
                        prevTimeSlotArrayList.Add(temp);
                    }
                }
            }
        }

        /// <summary>
        /// Just a way to let the admin/staff view the log before exiting application for certain
        /// (in case of app crash or alt+f4)
        /// </summary>
        private void window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            window.WindowState = System.Windows.WindowState.Minimized;
            Console.WriteLine("Exiting Application : " + DateTime.Now);
            //Console.WriteLine("Press any key to continue..");
            //Console.ReadLine();
        }

        #region Animation stuff
        /// <summary>
        /// Pans the viewport to center at the given point
        /// Uses a point animation to make the process gradual
        /// </summary>
        ///
        /// <param name="pointTo">the new point that should be map centre</param>
        /// <param name="hideMarkers">whether markers should be removed or kept</param>
        /// <param name="speedRatio">modifier to the rate of the animation. '0' or less
        /// will make default of 2</param>
        public bool mapIsPanning = false;
        public bool panTo(PointLatLng pointTo, bool hideMarkers, int speedRatio)
        {
            if (!mapIsPanning)
            {
                mapIsPanning = true;

                if (hideMarkers)
                {
                    MainMap.Markers.Clear();
                }


                //PointAnimation panMap = new PointAnimation();
                //panMap.Duration = TimeSpan.FromSeconds(0.5);
                //panMap.From = new Point(MainMap.Position.Lat, MainMap.Position.Lng);
                //panMap.To = new Point(pointTo.Lat, pointTo.Lng);
                //MainMap.BeginAnimation(MapPointProperty, panMap);
                //panMap = null;


                double dx = MainMap.Position.Lng - mapCenterPosition.Lng;
                double dy = MainMap.Position.Lat - mapCenterPosition.Lat;
                double positionDiff = Math.Sqrt(dx * dx + dy * dy);

                //Console.WriteLine("distance = " + positionDiff.ToString());
                PointAnimation panMap = new PointAnimation();
                if (positionDiff > 0)
                {
                    panMap.Duration = TimeSpan.FromSeconds(positionDiff);
                }
                else
                {
                    panMap.Duration = TimeSpan.FromSeconds(1);//default
                }

                if (speedRatio <= 0)
                {
                    panMap.SpeedRatio = 2;
                }
                else
                {
                    panMap.SpeedRatio = speedRatio;
                }


                panMap.From = new Point(MainMap.Position.Lat, MainMap.Position.Lng);
                panMap.To = new Point(pointTo.Lat, pointTo.Lng);
                Storyboard.SetTarget(panMap, MainMap);
                Storyboard.SetTargetProperty(panMap, new PropertyPath(MapPointProperty));
                panMapStoryBoard.Children.Clear();
                panMapStoryBoard.Children.Add(panMap);
                panMapStoryBoard.Begin(this);
                panMap = null;

                return true;
            }
            else
            {
                return false;
            }

        }

        bool reloadAfterPan = false;
        void panMapStoryBoard_Completed(object sender, EventArgs e)
        {
            mapIsPanning = false;

            if (reloadAfterPan)
            {
                ReloadStories(true);
                reloadAfterPan = false;
            }
        }


        public System.Windows.Point MapPoint
        {
            get { return (System.Windows.Point)GetValue(MapPointProperty); }
            set { SetValue(MapPointProperty, value); }
        }


        // Using a DependencyProperty as the backing store for point.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MapPointProperty =
               DependencyProperty.Register("MapPoint", typeof(System.Windows.Point), typeof(GMapControl), new PropertyMetadata(new Point(), OnMapPointPropertyChanged));


        private static void OnMapPointPropertyChanged(DependencyObject source,
        DependencyPropertyChangedEventArgs e)
        {
            Point temp = (Point)e.NewValue;
            PointLatLng gmapPoint = new PointLatLng(temp.X, temp.Y);
            (source as GMapControl).Position = gmapPoint;
        }
        #endregion


        #region Watchout! Its unmanaged code (interop - keybd_event - send keys, etc.)
        const int KEYEVENTF_EXTENDEDKEY = 0x1;
        const int KEYEVENTF_KEYUP = 0x2;

        [DllImport("user32.dll")]
        static extern void keybd_event(byte key, byte scan, int flags, int extraInfo);

        new public static void KeyDown(System.Windows.Forms.Keys key)
        {
            keybd_event(ParseKey(key), 0, 0, 0);
        }

        new public static void KeyUp(System.Windows.Forms.Keys key)
        {
            keybd_event(ParseKey(key), 0, KEYEVENTF_KEYUP, 0);
        }

        public static void KeyPress(System.Windows.Forms.Keys key)
        {
            KeyDown(key);
            KeyUp(key);
        }

        static byte ParseKey(System.Windows.Forms.Keys key)
        {
            // Alt, Shift, and Control need to be changed for API function to work with them
            switch (key)
            {
                case System.Windows.Forms.Keys.Alt:
                    return (byte)18;
                case System.Windows.Forms.Keys.Control:
                    return (byte)17;
                case System.Windows.Forms.Keys.Shift:
                    return (byte)16;
                default:
                    return (byte)key;
            }
        }
        #endregion

        //test if drag is within auckland boundary
        private void window_DragOver(object sender, DragEventArgs e)
        {
            //validStoryBoundary
            //check if current mouse pos is within the rectLatLng bounds

            Point mousePos = e.GetPosition(window);
            PointLatLng mousePosLatLng = MainMap.FromLocalToLatLng((int)mousePos.X, (int)mousePos.Y);


            if (!checkBounds(validStoryBoundary, mousePosLatLng))//if outside of bounds do not allow drop
            {
                e.Effects = DragDropEffects.None;
            }

            else
            {
                //  e.Effects = DragDropEffects.None;
            }
        }

        private bool checkBounds(RectLatLng rectLatLng, PointLatLng posLatLng)
        {
            if (rectLatLng.Contains(posLatLng))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private void button_start_MouseUp(object sender, MouseButtonEventArgs e)
        {
            button_start.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_start.png", UriKind.Relative));
            displayWelcomeScreen();
        }

        private void button_start_MouseDown(object sender, MouseButtonEventArgs e)
        {
            button_start.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_start_pressed.png", UriKind.Relative));
        }

        private void button_start_MouseLeave(object sender, MouseEventArgs e)
        {
            button_start.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_start.png", UriKind.Relative));
        }

        private void button_addstory_MouseUp(object sender, MouseButtonEventArgs e)
        {
            if (welcomeActive)
            {
                button_addstory.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_addstory.png", UriKind.Relative));
                closeWelcomeScreen();
            }
            else
            {
                button_addstory.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_addanotherstory.png", UriKind.Relative));
                readMode = false;
                CloseStoryInput(false);
            }
            WriteStoryMode();
        }

        private void button_addstory_MouseDown(object sender, MouseButtonEventArgs e)
        {
            if (welcomeActive)
            {
                button_addstory.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_addstory_pressed.png", UriKind.Relative));
            }
            else
            {
                button_addstory.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_addanotherstory_pressed.png", UriKind.Relative));
            }
        }

        private void button_addstory_MouseLeave(object sender, MouseEventArgs e)
        {
            if (welcomeActive)
            {
                button_addstory.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_addstory.png", UriKind.Relative));
            }
            else
            {
                button_addstory.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_addanotherstory.png", UriKind.Relative));
            }
        }

        private void button_readstory_MouseUp(object sender, MouseButtonEventArgs e)
        {
            if (sender == button_readstory)//if the read button not the bubble
            {
                button_readstory.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_readstory.png", UriKind.Relative));
            }

            if (welcomeActive)
            {
                closeWelcomeScreen();
            }
            else
            {
                readMode = true;
                CloseStoryInput(false);
            }
            ReadStoryMode();
        }

        private void button_readstory_MouseDown(object sender, MouseButtonEventArgs e)
        {
            if (sender == button_readstory)//if the read button not the bubble
            {
                button_readstory.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_readstory_pressed.png", UriKind.Relative));
            }
        }

        private void button_readstory_MouseLeave(object sender, MouseEventArgs e)
        {
            if (sender == button_readstory)//if the read button not the bubble
            {
                button_readstory.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_readstory.png", UriKind.Relative));
            }
        }

        private void cancelStoryInputCatImgBtn_MouseUp(object sender, MouseButtonEventArgs e)
        {
            CloseStoryInput(false);
            cancelStoryInputCatImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_X.png", UriKind.Relative));
        }

        private void cancelStoryInputCatImgBtn_MouseDown(object sender, MouseButtonEventArgs e)
        {
            cancelStoryInputCatImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_X_down.png", UriKind.Relative));
        }

        private void cancelStoryInputCatImgBtn_MouseLeave(object sender, MouseEventArgs e)
        {
            cancelStoryInputCatImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_X.png", UriKind.Relative));
        }

        private void backStoryInputCatImgBtn_MouseLeave(object sender, MouseEventArgs e)
        {
            backStoryInputCatImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_back.png", UriKind.Relative));
        }

        private void backStoryInputCatImgBtn_MouseDown(object sender, MouseButtonEventArgs e)
        {
            backStoryInputCatImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_back_down.png", UriKind.Relative));
        }

        private void backStoryInputCatImgBtn_MouseUp(object sender, MouseButtonEventArgs e)
        {
            //go back to time select page
            //addStoryCatCanvas.Visibility = System.Windows.Visibility.Hidden;
            InputStoryText();
            backStoryInputCatImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_back.png", UriKind.Relative));
        }

        private void cancelStoryInputTimeImgBtn_MouseUp(object sender, MouseButtonEventArgs e)
        {
            CloseStoryInput(false);
            cancelStoryInputTimeImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_X.png", UriKind.Relative));
        }

        private void cancelStoryInputTimeImgBtn_MouseDown(object sender, MouseButtonEventArgs e)
        {
            cancelStoryInputTimeImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_X_down.png", UriKind.Relative));
        }

        private void cancelStoryInputTimeImgBtn_MouseLeave(object sender, MouseEventArgs e)
        {
            cancelStoryInputTimeImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_X.png", UriKind.Relative));
        }

        private void backStoryInputTimeImgBtn_MouseLeave(object sender, MouseEventArgs e)
        {
            backStoryInputTimeImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_back.png", UriKind.Relative));
        }

        private void backStoryInputTimeImgBtn_MouseDown(object sender, MouseButtonEventArgs e)
        {
            backStoryInputTimeImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_back_down.png", UriKind.Relative));
        }

        private void backStoryInputTimeImgBtn_MouseUp(object sender, MouseButtonEventArgs e)
        {
            CloseStoryInput(false);
            backStoryInputTimeImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_back.png", UriKind.Relative));
        }

        private void cancelStoryInputTextImgBtn_MouseUp(object sender, MouseButtonEventArgs e)
        {
            CloseKeyboard();
            if (storyInputTextBox.AreSuggestionsVisible)
            {
                storyInputTextBox.HideSuggestions();
            }
            if (storyTitleInputTextBox.AreSuggestionsVisible)
            {
                storyTitleInputTextBox.HideSuggestions();
            }
            CloseStoryInput(false);
            cancelStoryInputTextImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_X.png", UriKind.Relative));
        }

        private void cancelStoryInputTextImgBtn_MouseDown(object sender, MouseButtonEventArgs e)
        {
            cancelStoryInputTextImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_X_down.png", UriKind.Relative));
        }

        private void cancelStoryInputTextImgBtn_MouseLeave(object sender, MouseEventArgs e)
        {
            cancelStoryInputTextImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_X.png", UriKind.Relative));
        }

        private void backStoryInputTextImgBtn_MouseLeave(object sender, MouseEventArgs e)
        {
            backStoryInputTextImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_back.png", UriKind.Relative));
        }

        private void backStoryInputTextImgBtn_MouseDown(object sender, MouseButtonEventArgs e)
        {
            backStoryInputTextImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_back_down.png", UriKind.Relative));
        }

        private void backStoryInputTextImgBtn_MouseUp(object sender, MouseButtonEventArgs e)
        {
            //go back to time select page
            //addStoryTextCanvas.Visibility = System.Windows.Visibility.Hidden;
            CloseKeyboard();
            if (storyInputTextBox.AreSuggestionsVisible)
            {
                storyInputTextBox.HideSuggestions();
            }
            if (storyTitleInputTextBox.AreSuggestionsVisible)
            {
                storyTitleInputTextBox.HideSuggestions();
            }
            NewInputStory(true);
            backStoryInputTextImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_back.png", UriKind.Relative));
        }

        private void button_time_continue_MouseDown(object sender, MouseButtonEventArgs e)
        {
            button_time_continue.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_continue_pressed.png", UriKind.Relative));
        }

        private void button_time_continue_MouseUp(object sender, MouseButtonEventArgs e)
        {
            if (aTimeSlotHasBeenSelected)
            {
                pulseOverTimeSlot.Visibility = System.Windows.Visibility.Visible;
                Storyboard fade = (Storyboard)Resources["TimeSlotInputFadeInThenOut"];
                fade.Begin();
                //showGrowlNotification(newStoryValidation, newStoryValidationTitle, newStoryTimeNotSelectedNotification);

                button_time_continue.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_continue.png", UriKind.Relative));
                InputStoryText();
            }
        }

        private void button_time_continue_MouseLeave(object sender, MouseEventArgs e)
        {
            button_time_continue.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_continue.png", UriKind.Relative));
        }

        private void button_text_continue_MouseDown(object sender, MouseButtonEventArgs e)
        {
            button_text_continue.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_continue_pressed.png", UriKind.Relative));
        }

        private void button_text_continue_MouseUp(object sender, MouseButtonEventArgs e)
        {
            if (storyInputTextBox.Text.Length > 0)
            {
                //pulse over the input area
                pulseOverStory.Visibility = System.Windows.Visibility.Visible;
                Storyboard fade = (Storyboard)Resources["StoryInputFadeInThenOut"];
                fade.Begin();
                //showGrowlNotification(newStoryValidation, newStoryValidationTitle, newStoryTextNotTypedNotification);

                button_text_continue.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_continue.png", UriKind.Relative));

                if (storyInputTextBox.AreSuggestionsVisible)
                {
                    storyInputTextBox.HideSuggestions();
                }

                if (storyTitleInputTextBox.AreSuggestionsVisible)
                {
                    storyTitleInputTextBox.HideSuggestions();
                }

                CloseKeyboard();
                InputStoryCategory();
            }
        }

        private void button_text_continue_MouseLeave(object sender, MouseEventArgs e)
        {
            button_text_continue.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_continue.png", UriKind.Relative));
        }

        private void button_publish_MouseDown(object sender, MouseButtonEventArgs e)
        {
            button_publish.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_publishstory_pressed.png", UriKind.Relative));
        }

        bool publishButtonTimeoutActive = false;
        private void button_publish_MouseUp(object sender, MouseButtonEventArgs e)
        {
            if (!publishButtonTimeoutActive) //if button has not been pressed yet
            {
                //readMode = false;  //stops the newly added story popping up
                publishButtonTimeoutActive = true;//prevents this from running again soon
                System.Timers.Timer timeout = new System.Timers.Timer();
                timeout.Elapsed += new System.Timers.ElapsedEventHandler(timeout_Elapsed);
                timeout.Interval = 5000; //5 seconds before this event can happen again
                timeout.Start();

                if (IsItASecretAdminCommand(storyInputTextBox.Text))
                {
                    CloseStoryInput(false);
                }
                else //its not an admin command
                {
                    //if (aCategoryHasBeenSelected)
                    //{
                    //    pulseOverCategories.Visibility = System.Windows.Visibility.Visible;
                    //    Storyboard fade = (Storyboard)Resources["CategoryInputFadeInThenOut"];
                    //    fade.Begin();
                        //showGrowlNotification(newStoryValidation, newStoryValidationTitle, newStoryCategoryNotSelectedNotification);


                        Cursor = Cursors.Wait;
                        string filteredStory = AddStoryToRemoteDB(currentStoryType, FilterTheStoryFromBadChars(storyInputTextBox.Text), currentPosition, currentTimeSlotType, FilterTheStoryFromBadChars(storyTitleInputTextBox.Text));
                        string[] tempStory = filteredStory.Split(stringSplitChar);

                        filteredStory = tempStory[0];
                        string title = tempStory[1];
                        myStoryLifetime.Stop();
                        myStoryLifetime.Elapsed -= new System.Timers.ElapsedEventHandler(myStoryLifetime_Elapsed);//remove any existing timer
                        myStoryLifetime.Elapsed += new System.Timers.ElapsedEventHandler(myStoryLifetime_Elapsed);
                        myStoryLifetime.Interval = UserStoryLifetime;
                        myStoryLifetime.Start();
                        Cursor = Cursors.Arrow;

                        try
                        {
                            long idOfNewStory = Convert.ToInt64(tempStory[2]);
                            if (tempStory[1].Equals("-1")) //-1 id means story matched filtered words
                            {
                                //show message to user
                                addMarkerToMap(currentPosition, "", "", currentStoryType, true, idOfNewStory, currentTimeSlotType, true, null, true);
                            }
                            else
                            {
                                addMarkerToMap(currentPosition, filteredStory, title, currentStoryType, true, idOfNewStory, currentTimeSlotType, true, null, true);
                            }
                            Story temp = new Story(idOfNewStory, currentStoryType, currentTimeSlotType, currentPosition.Lat, currentPosition.Lng, filteredStory, null, title);
                            temp.ShowBubble = true;
                            myStoriesArrayList.Add(temp);
                            sendUpdateMessage(temp);//send update message
                        }
                        catch
                        {
                            //if there was an error, still add the story but show error message
                            addMarkerToMap(currentPosition, filteredStory, title, currentStoryType, true, -1, currentTimeSlotType, true, null, true);
                        }


                        storyJustSubmitted = true;
                        CloseStoryInput(false);
                        ReadStoryMode();
                        ////show the thankyou screen
                        //ShowStorySubmittedScreen();

                    }
                //}
                button_publish.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_publishstory.png", UriKind.Relative));
                e.Handled = true;
            }
        }

        //resets the timeout publish button variable to allow publishing again
        void timeout_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            publishButtonTimeoutActive = false;
            (sender as System.Timers.Timer).Stop();
            (sender as System.Timers.Timer).Elapsed -= new System.Timers.ElapsedEventHandler(timeout_Elapsed);
            sender = null;
        }

        private void button_publish_MouseLeave(object sender, MouseEventArgs e)
        {
            button_publish.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_publishstory.png", UriKind.Relative));
        }

        private void readMode_MouseDown(object sender, MouseButtonEventArgs e)
        {
            readModeBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_small_readstory_down.png", UriKind.Relative));
        }

        private void readMode_MouseUp(object sender, MouseButtonEventArgs e)
        {
            readModeBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_small_readstory.png", UriKind.Relative));
            ReadStoryMode();
        }

        private void writeMode_MouseDown(object sender, MouseButtonEventArgs e)
        {
            writeModeBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_small_writestory_down.png", UriKind.Relative));
        }

        private void writeMode_MouseUp(object sender, MouseButtonEventArgs e)
        {
            writeModeBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_small_writestory.png", UriKind.Relative));
            WriteStoryMode();
        }

        private void writeModeBtn_MouseLeave(object sender, MouseEventArgs e)
        {
            writeModeBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_small_writestory.png", UriKind.Relative));
        }

        private void readModeBtn_MouseLeave(object sender, MouseEventArgs e)
        {
            readModeBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_small_readstory.png", UriKind.Relative));
        }

        private void addStoryMarker_MouseDown(object sender, MouseButtonEventArgs e)
        {
            addStoryMarker.Visibility = Visibility.Hidden;
            addStoryMarker.VerticalAlignment = System.Windows.VerticalAlignment.Top;
            addStoryMarker.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
            addStoryMarker.Margin = new Thickness(-100, -100, 0, 0);//prevents bug which stops drag drop onto original image of location


            bubble_draganddropme.Visibility = Visibility.Hidden;

            if (helpDialogueCanvas.Visibility == System.Windows.Visibility.Visible)
            {
                fadeOutHelpCanvas(false);
            }

            DragDrop.DoDragDrop((System.Windows.DependencyObject)sender, sender, DragDropEffects.Copy);
            aCategoryHasBeenSelected = false;
            aTimeSlotHasBeenSelected = false;
            VerifyIfStoryCanBeSubmitted(false);
        }

        private void button_yes_MouseDown(object sender, MouseButtonEventArgs e)
        {
            button_yes.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_yes_pressed.png", UriKind.Relative));
        }

        private void button_yes_MouseUp(object sender, MouseButtonEventArgs e)
        {
            button_yes.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_yes.png", UriKind.Relative));

            HideConfirmPositionCanvas();

            NewInputStory(false);
        }

        private void button_yes_MouseLeave(object sender, MouseEventArgs e)
        {
            button_yes.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_yes.png", UriKind.Relative));
        }

        private void button_tryagain_MouseDown(object sender, MouseButtonEventArgs e)
        {
            button_tryagain.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_tryagain_pressed.png", UriKind.Relative));
        }

        private void button_tryagain_MouseUp(object sender, MouseButtonEventArgs e)
        {
            button_tryagain.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_tryagain.png", UriKind.Relative));

            HideConfirmPositionCanvas();

            Storyboard rectfadeOut = (Storyboard)Resources["blackRectCanvasFadeOut"];
            rectfadeOut.Begin();
        }

        private void button_tryagain_MouseLeave(object sender, MouseEventArgs e)
        {
            button_tryagain.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_tryagain.png", UriKind.Relative));
        }

        private void fadingOutConfirmCanvas_Completed(object sender, EventArgs e)
        {
            confirmPositionCanvas.Visibility = System.Windows.Visibility.Hidden;
        }

        private void hideFilter_Completed(object sender, EventArgs e)
        {
            if (readMode)
            {
                showFilterPanelImgBtn.Visibility = Visibility.Visible;
                showButtonRect.Visibility = Visibility.Visible;
            }

            filterCanvas.Visibility = Visibility.Hidden;

            isFilterAnimationRunning = false;
        }

        private void showFilter_Completed(object sender, EventArgs e)
        {
            isFilterAnimationRunning = false;
        }

        private void QueryContinueDragEventHandler(object sender, QueryContinueDragEventArgs e)
        {
            if (e.KeyStates != DragDropKeyStates.LeftMouseButton)
            {
                addStoryMarker.VerticalAlignment = System.Windows.VerticalAlignment.Bottom;
                addStoryMarker.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
                addStoryMarker.Margin = new Thickness(20, 0, 0, 100); //go back to default
                addStoryMarker.Visibility = Visibility.Visible;
            }

            //if (e.KeyStates == DragDropKeyStates.None) //alt method 
            //{
            //    addStoryMarker.VerticalAlignment = System.Windows.VerticalAlignment.Center;
            //    addStoryMarker.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
            //    addStoryMarker.Margin = new Thickness(0, 0, 0, 0); //go back to centre screen
            //    addStoryMarker.Visibility = Visibility.Visible;
            //}
        }

        private void hideButtonRect_MouseDown(object sender, MouseButtonEventArgs e)
        {
            hideFilterPanelImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_hide_down.png", UriKind.Relative));
        }

        private void hideButtonRect_MouseUp(object sender, MouseButtonEventArgs e)
        {
            if (!isFilterAnimationRunning) //disable until animation is done
            {
                hideFilterPanelImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_hide.png", UriKind.Relative));
                HideFilterCanvas();
            }
        }

        private void hideButtonRect_MouseLeave(object sender, MouseEventArgs e)
        {
            hideFilterPanelImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_hide.png", UriKind.Relative));
        }

        private void showButtonRect_MouseDown(object sender, MouseButtonEventArgs e)
        {
            showFilterPanelImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_show_down.png", UriKind.Relative));
        }

        private void showButtonRect_MouseUp(object sender, MouseButtonEventArgs e)
        {
            if (!isFilterAnimationRunning) //disable until animation is done
            {
                showFilterPanelImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_show.png", UriKind.Relative));
                ShowFilterCanvas();
            }
        }

        private void showButtonRect_MouseLeave(object sender, MouseEventArgs e)
        {
            showFilterPanelImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_show.png", UriKind.Relative));
        }

        private void XButtonRect6_MouseDown(object sender, MouseButtonEventArgs e)
        {
            if (sender is Image)//the done button
            {
                button_done.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_done_pressed.png", UriKind.Relative));
            }
            else
            {
                cancelStoryReadImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_X_down.png", UriKind.Relative));
            }
        }

        private void XButtonRect6_MouseUp(object sender, MouseButtonEventArgs e)
        {
            if (sender is Image)//the done button
            {
                button_done.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_done.png", UriKind.Relative));
            }
            else
            {
                cancelStoryReadImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_X.png", UriKind.Relative));
            }
            HideReadStoryCanvas();
            if (storyJustSubmitted)
            {
                storyJustSubmitted = false;
                ReloadStories(true);
            }
        }

        private void XButtonRect6_MouseLeave(object sender, MouseEventArgs e)
        {
            if (sender is Image)//the done button
            {
                button_done.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_done.png", UriKind.Relative));
            }
            else
            {
                cancelStoryReadImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_X.png", UriKind.Relative));
            }
        }

        private void button_report_MouseDown(object sender, MouseButtonEventArgs e)
        {
           // button_report.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_report_pressed.png", UriKind.Relative));
        }

        private void button_report_MouseLeave(object sender, MouseEventArgs e)
        {
           // button_report.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_report.png", UriKind.Relative));
        }

        private void button_report_MouseUp(object sender, MouseButtonEventArgs e)
        {
           // button_report.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_report.png", UriKind.Relative));
            bool storyFound = false;
            CustomMarker temp = null;
            foreach (GMapMarker gmark in MainMap.Markers)
            {
                if ((gmark.Shape as CustomMarker).thisMarkersPopupIsShowing)
                {
                    storyFound = true;
                    temp = (CustomMarker)gmark.Shape;
                    break;
                }
            }


            if (storyFound && !temp.reported)
            {
                //report story
                StoriesHelperClass.reportStoryToDB(temp.storyID);

                //content
                readStoryTextBlock.Text = "You have reported this story.\nThank you for helping us keep our stories safe.";
                readStoryTextBlock.FontSize = 26;
                //readStoryTextBlock.TextDecorations.Add(TextDecorations.Underline);
                readStoryTextBlock.Foreground = new SolidColorBrush(Color.FromArgb((byte)0xFF, (byte)0x40, (byte)0x81, (byte)0x9B));
                readStoryTextBlock.TextAlignment = TextAlignment.Left;

                //title
                readStoryTitleTextBlock.FontSize = 28;
                readStoryTitleTextBlock.TextDecorations.Add(TextDecorations.Underline);
                readStoryTitleTextBlock.Foreground = new SolidColorBrush(Color.FromArgb((byte)0xFF, (byte)0x40, (byte)0x81, (byte)0x9B));
                readStoryTitleTextBlock.TextAlignment = TextAlignment.Left;
                readStoryTitleTextBlock.Text = "STORY REPORTED";

                report_text.IsEnabled = false;
                report_text.Opacity = 0.2;
                temp.reported = true;


                //remove story from this session
                storyManager.RemoveStoriesFromDB(temp.storyID);
                MainMap.Markers.Remove(temp.Marker);
            }
        }

        private void hideReadCanvas_Completed(object sender, EventArgs e)
        {
            readStoryCanvas.Visibility = Visibility.Hidden;
        }

        private void filterCanvas_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            //center horizontally on canvas
            Canvas.SetLeft(hideFilterPanelImgBtn, (filterCanvas.ActualWidth - hideFilterPanelImgBtn.ActualWidth) / 2);
            Canvas.SetLeft(hideButtonRect, (filterCanvas.ActualWidth - hideButtonRect.ActualWidth) / 2);
            Canvas.SetLeft(vert_line, (filterCanvas.ActualWidth - vert_line.ActualWidth) / 2);

            //reposition on canvas
            Canvas.SetLeft(lbl_timedesc, (filterCanvas.ActualWidth / 2) + 100);
            Canvas.SetLeft(timeslotFilterGrid, (filterCanvas.ActualWidth / 2) + 100);

            Canvas.SetLeft(lbl_categorydesc, (filterCanvas.ActualWidth / 2) - 100 - lbl_categorydesc.ActualWidth + 10);
            Canvas.SetLeft(categoryFilterGrid, (filterCanvas.ActualWidth / 2) - 100 - categoryFilterGrid.ActualWidth + 10);
        }

        private void floatingTouchScreenKeyboard1_PreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            idleTimer.Stop();
            idleTimer.Start();
            idleTimerRunCount = 0;
        }

        //terms of use
        private void labelRect1_MouseUp(object sender, MouseButtonEventArgs e)
        {
            if (termsOfUseCanvas.Visibility == Visibility.Hidden)
            {
                shouldReloadOnTouch = false;
                termsOfUseCanvas.Visibility = Visibility.Visible;
                termsOfUseCanvas.Opacity = 0;
                Storyboard fadeIn = (Storyboard)Resources["TermsCanvasFadeIn"];
                fadeIn.Begin();

                ////plus the rectangle behind it
                //blackRectangleCanvas.Visibility = System.Windows.Visibility.Visible;
                //blackRectangleCanvas.Opacity = 0;
                //blackRectangleCanvas.Height = window.Height;
                //blackRectangleCanvas.Width = window.Width;
                //Storyboard fadeInRect = (Storyboard)Resources["blackRectCanvasDarkFadeIn"];
                //fadeInRect.Begin();
            }
        }

        private void labelRect1_MouseDown(object sender, MouseButtonEventArgs e)
        {

        }

        private void labelRect1_MouseLeave(object sender, MouseEventArgs e)
        {

        }

        private void button_category_continue_MouseDown(object sender, MouseButtonEventArgs e)
        {
            button_category_continue.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_continue_pressed.png", UriKind.Relative));
        }

        private void button_category_continue_MouseLeave(object sender, MouseEventArgs e)
        {
            button_category_continue.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_continue.png", UriKind.Relative));
        }

        private void button_category_continue_MouseUp(object sender, MouseButtonEventArgs e)
        {
            button_category_continue.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_continue.png", UriKind.Relative));
            
            //Storyboard fadeOut = (Storyboard)Resources["StoryCanvasCatFadeOut"];
           // fadeOut.Begin();

            InputStoryNearlyThere();
        }

        //back button
        private void nearlyThereBackImgBtn_MouseDown(object sender, MouseButtonEventArgs e)
        {
            backNearlyThereImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_back_down.png", UriKind.Relative));
        }

        private void nearlyThereBackImgBtn_MouseLeave(object sender, MouseEventArgs e)
        {
            backNearlyThereImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_back.png", UriKind.Relative));
        }

        private void nearlyThereBackImgBtn_MouseUp(object sender, MouseButtonEventArgs e)
        {
            backNearlyThereImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_back.png", UriKind.Relative));
            InputStoryCategory();
        }

        //cancel button
        private void nearlyThereImgBtn_MouseLeave(object sender, MouseEventArgs e)
        {
            cancelNearlyThereImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_X.png", UriKind.Relative));
        }

        private void nearlyThereImgBtn_MouseDown(object sender, MouseButtonEventArgs e)
        {
            cancelNearlyThereImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_X_down.png", UriKind.Relative));
        }

        private void nearlyThereImgBtn_MouseUp(object sender, MouseButtonEventArgs e)
        {
            CloseStoryInput(false);
            cancelNearlyThereImgBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_X.png", UriKind.Relative));
        }

        private void storyCanvasNearlyThereFadeOut_Completed(object sender, EventArgs e)
        {
            nearlyThereCanvas.Visibility = System.Windows.Visibility.Hidden;
        }

        private void termsRect_MouseDown(object sender, MouseButtonEventArgs e)
        {

        }

        private void termsRect_MouseLeave(object sender, MouseEventArgs e)
        {

        }

        private void termsRect_MouseUp(object sender, MouseButtonEventArgs e)
        {
            if (termsOfUseCanvas.Visibility == Visibility.Hidden)
            {
                termsOfUseCanvas.Visibility = Visibility.Visible;
                termsOfUseCanvas.Opacity = 0;
                Storyboard fadeIn = (Storyboard)Resources["TermsCanvasFadeIn"];
                fadeIn.Begin();

                fadeOutHelpCanvas(true);

                termsNestedInHelpCanvas = true;

                ////plus the rectangle behind it
                //blackRectangleCanvas.Visibility = System.Windows.Visibility.Visible;
                //blackRectangleCanvas.Opacity = 0;
                //blackRectangleCanvas.Height = window.Height;
                //blackRectangleCanvas.Width = window.Width;
                //Storyboard fadeInRect = (Storyboard)Resources["blackRectCanvasDarkFadeIn"];
                //fadeInRect.Begin();
            }
        }

        private void termsOfUseCanvasExitImageBtn_MouseUp(object sender, MouseButtonEventArgs e)
        {
            fadeOutTermsCanvas();

            if (termsNestedInHelpCanvas && helpDialogueCanvas.Visibility == Visibility.Hidden)
            {
                termsNestedInHelpCanvas = false;
                helpDialogueCanvas.Visibility = Visibility.Visible;
                helpDialogueCanvas.Opacity = 0;
                Storyboard fadeIn = (Storyboard)Resources["HelpCanvasFadeIn"];
                fadeIn.Begin();
            }

            termsOfUseCanvasExitImageBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_X.png", UriKind.Relative));
        }
        private void termsOfUseCanvasExitImageBtn_MouseDown(object sender, MouseButtonEventArgs e)
        {
            termsOfUseCanvasExitImageBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_X_down.png", UriKind.Relative));
        }
        private void termsOfUseCanvasExitImageBtn_MouseLeave(object sender, MouseEventArgs e)
        {
            termsOfUseCanvasExitImageBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_X.png", UriKind.Relative));
        }

        private void button_agree_MouseDown(object sender, MouseButtonEventArgs e)
        {
            button_agree.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_agree_pressed.png", UriKind.Relative));
        }

        private void button_agree_MouseUp(object sender, MouseButtonEventArgs e)
        {
            fadeOutTermsCanvas();

            if (termsNestedInHelpCanvas && helpDialogueCanvas.Visibility == Visibility.Hidden)
            {
                termsNestedInHelpCanvas = false;
                helpDialogueCanvas.Visibility = Visibility.Visible;
                helpDialogueCanvas.Opacity = 0;
                Storyboard fadeIn = (Storyboard)Resources["HelpCanvasFadeIn"];
                fadeIn.Begin();
            }

            button_agree.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_agree.png", UriKind.Relative));
        }

        private void button_agree_MouseLeave(object sender, MouseEventArgs e)
        {
            button_agree.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_agree.png", UriKind.Relative));
        }

        private void button_help_done_MouseDown(object sender, MouseButtonEventArgs e)
        {
            button_help_done.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_done_pressed.png", UriKind.Relative));
        }

        private void button_help_done_MouseUp(object sender, MouseButtonEventArgs e)
        {
            button_help_done.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_done.png", UriKind.Relative));
            fadeOutHelpCanvas(false);
        }

        private void button_help_done_MouseLeave(object sender, MouseEventArgs e)
        {
            button_help_done.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_done.png", UriKind.Relative));
        }

        private void homeBtn_MouseDown(object sender, MouseButtonEventArgs e)
        {
            homeBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_small_home_down.png", UriKind.Relative));
        }

        private void homeBtn_MouseLeave(object sender, MouseEventArgs e)
        {
            homeBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_small_home.png", UriKind.Relative));
        }

        private void homeBtn_MouseUp(object sender, MouseButtonEventArgs e)
        {
            homeBtn.Source = new BitmapImage(new Uri("/InteractiveMapApp;component/Images/button_small_home.png", UriKind.Relative));
            ResetAppToDefaultState();
        }

        private void fadeInHelpCanvas_Completed(object sender, EventArgs e)
        {
            howManyTimesCanIdleTimerRunConsequentlyBeforeResetAppToDefaultState = 18;
        }
    }
}
#region Archived Code Library
/*
 * fetch recent
 */
////add previously recent stories into the main list
//if (recentStoriesArrayList != null)
//{
//    //storiesArrayList.AddRange(recentStoriesArrayList);
//    Console.WriteLine("TODO : FETCHRECENT; SEND NEW TORIES TO LOCALDB");
//}
//recentStoriesArrayList = new ArrayList(); //clear any previously 'recent' stories

//string downloadedRecentStories = downloadRequestFromDB(LOADRECENTSTORYREQUEST);
//if (downloadedRecentStories.Equals("0001234")) //means an exception occurred when downloading categories
//{
//    //TODO : do something here in case server not available...
//}
//else
//{
//    if (downloadedRecentStories.Equals(""))
//    {
//    }
//    else
//    {
//        string[] recentStoriesArray = downloadedRecentStories.Split(stringSplitChar);
//        int i = 0;
//        int countNewStories = 0;
//        while (i < recentStoriesArray.Length - 1)
//        {
//            int index = 0;
//            bool found = false;
//            //check if story is already inside mystoriesarraylist (new one created from this pc)
//            foreach (Story story in myStoriesArrayList)
//            {
//                if (story.StoryID == Convert.ToInt32(recentStoriesArray[i]))
//                {
//                    found = true;
//                }
//                index++;
//            }

//            //if it wasnt new one created just now.. check if we already downloaded it & got it here!
//            if (!found)
//            {
//                foreach (Story story in storiesArrayList)
//                {
//                    if (story.StoryID == Convert.ToInt32(recentStoriesArray[i]))
//                    {
//                        found = true;
//                    }
//                    index++;
//                }
//            }

//            //if it wasn't found at mystories or stories arraylist, add it to recent stories arraylist
//            if (!found)
//            {
//                recentStoriesArrayList.Add(new Story(Convert.ToInt32(recentStoriesArray[i]), Convert.ToInt32(recentStoriesArray[i + 1]),
//                    Convert.ToInt32(recentStoriesArray[i + 2]), Convert.ToDouble(recentStoriesArray[i + 3]),
//                    Convert.ToDouble(recentStoriesArray[i + 4]), recentStoriesArray[i + 5]));
//                countNewStories++;
//                //MessageBox.Show("new story added to recentStoriesArrayList!");
//            }

//            i += 6;
//        }
//        //if there was some new stories, show notification about it!
//        if (countNewStories > 0)
//        {
//            showGrowlNotification(newStoryValidation, updatedWithNewStoriesTitle, countNewStories.ToString() + " " + updatedWithNewStoriesNotification);
//        }
//    }
//}


/// <summary>
// takes the result (string array) from downloadRequestFromDB() method, 
// splits them and creates a story object array out of it.
//This array is used to manipulate which stories should be displayed.
// This method also calls the addMarkerToMap() method which draws the stories
//// to the map
//// </summary>
//// <param name="onlyRefresh">Whether stories should be refreshed or re-fetched</param>
//private void addDownloadedMarkersToMap(bool onlyRefresh)
//{
//    string downloadedStories = "";
//    if (!onlyRefresh)
//    {
//        downloadedStories = downloadRequestFromDB(LOADSTORYREQUEST);
//        //MessageBox.Show(downloadedStories);
//    }
//    //else
//    //{
//        //fetchRecentStories();
//    //}

//    if (downloadedStories.Equals("0001234")) //means an exception occurred when downloading stories
//    {
//        //load 'backup'/default markers in since theres some error which stopped app from loading all the markers
//        loadUpPhonyStories();
//    }
//    else
//    {
//        if (downloadedStories.Equals("") && !onlyRefresh)
//        {
//            //MessageBox.Show("no results returned");
//            loadUpPhonyStories();
//        }
//        else
//        {
//            if (!onlyRefresh)
//            {
//                //clear all existing stories for entire story list download
//                storiesArrayList = new ArrayList();
//                myStoriesArrayList = new ArrayList();
//                recentStoriesArrayList = new ArrayList();

//                string[] tempStoriesArray = downloadedStories.Split(stringSplitChar);
//                //MessageBox.Show(downloadedStories);
//                int a = 0;
//                while (a < tempStoriesArray.Length - 1)
//                {
//                    storiesArrayList.Add(new Story(Convert.ToInt32(tempStoriesArray[a]), Convert.ToInt32(tempStoriesArray[a + 1]),
//                        Convert.ToInt32(tempStoriesArray[a + 2]), Convert.ToDouble(tempStoriesArray[a + 3]), Convert.ToDouble(tempStoriesArray[a + 4]),
//                        tempStoriesArray[a + 5].ToString()));
//                    a += 6;
//                }
//            }

//            //filter lists of stories
//            ArrayList filteredStories = filterStories(storiesArrayList);
//            ArrayList filteredMyStories = filterStories(myStoriesArrayList);        //do we filter user stories??
//            ArrayList filteredRecentStories = filterStories(recentStoriesArrayList);
//            //ArrayList filteredMusuemStories = filterStories(museumStoriesArrayList);
//            ArrayList filteredMusuemStories = museumStoriesArrayList;

//            int totalOfAllCurrentStories = filteredStories.Count + filteredMyStories.Count + filteredRecentStories.Count;
//            //showGrowlNotification(filterApplied, filterAppliedTitle, filtersAppliedNotification + ". " + totalOfAllCurrentStories.ToString() + "stories available.");

//            Story[] randomStories;
//            Random random = new Random();

//            if (filteredStories.Count + filteredMyStories.Count + filteredRecentStories.Count + filteredMusuemStories.Count < MaxNumberTotalStoriesToShowAtATime)
//            {
//                randomStories = new Story[(filteredStories.Count + filteredMyStories.Count + filteredRecentStories.Count + filteredMusuemStories.Count)];
//            }
//            else
//            {
//                randomStories = new Story[MaxNumberTotalStoriesToShowAtATime];
//            }


//            selectRandomItems(filteredMusuemStories, randomStories, MaxNumberMuseumStoriesToShowAtATime);
//            selectRandomItems(filteredMyStories, randomStories, MaxNumberMyStoriesToShowAtATime);
//            selectRandomItems(filteredRecentStories, randomStories, MaxNumberRecentStoriesToShowAtATime);
//            selectRandomItems(filteredStories, randomStories, MaxNumberRandomStoriesToShowAtATime);


//            //sort the story array so that the objects with higher latitudes are listed first in the array
//            //uses the selection sort algorithm
//            int minNum;
//            for (int j = 0; j < randomStories.Length - 1; j++)
//            {
//                if (randomStories[j] != null)
//                {
//                    //assign value to value of the incrementer
//                    minNum = j;

//                    for (int k = j + 1; k < randomStories.Length; k++)
//                    {
//                        if (randomStories[k] != null)
//                        {
//                            //check this index of the array to see if it's smaller
//                            //than the index of the second loop
//                            if (randomStories[minNum].StoryLatLng.Lat < randomStories[k].StoryLatLng.Lat)
//                            {
//                                minNum = k;
//                            }
//                        }
//                    }

//                    if (minNum != j)//sorts the objects
//                    {
//                        Story tempStory;

//                        //temporary hold for attributes of object at the previous index
//                        int stID = randomStories[j].StoryID;
//                        int catID = randomStories[j].CategoryID;
//                        int timeID = randomStories[j].TimeSlotID;
//                        double latitude = randomStories[j].StoryLatLng.Lat;
//                        double longitude = randomStories[j].StoryLatLng.Lng;
//                        string content = randomStories[j].StoryContent;


//                        //sets the new object to the proper place in the array
//                        tempStory = new Story(randomStories[minNum].StoryID, randomStories[minNum].CategoryID, randomStories[minNum].TimeSlotID,
//                            randomStories[minNum].StoryLatLng.Lat, randomStories[minNum].StoryLatLng.Lng, randomStories[minNum].StoryContent);
//                        randomStories[j] = tempStory;

//                        //swaps the old objects position with the previous
//                        tempStory = new Story(stID, catID, timeID, latitude, longitude, content);
//                        randomStories[minNum] = tempStory;
//                    }

//                }
//            }


//            timerAddStories = randomStories;
//            timerAddStoryIndex = 0;
//            markerRedrawTimer.Tick += new EventHandler(addMarkerTimer_Tick);
//            markerRedrawTimer.Interval = 10;
//            markerRedrawTimer.Start();

//            //foreach(Story story in randomStories)
//            //{

//            //}



//            //if (timerAddStories != null && timerAddStoryIndex < timerAddStories.Length)
//            //{
//            //    if (timerAddStories[timerAddStoryIndex] != null)
//            //    {
//            //        PointLatLng storyPosition = new PointLatLng(timerAddStories[timerAddStoryIndex].StoryLatitude, timerAddStories[timerAddStoryIndex].StoryLongitude);
//            //        addMarkerToMap(storyPosition, timerAddStories[timerAddStoryIndex].StoryContent, timerAddStories[timerAddStoryIndex].CategoryID, false, timerAddStories[timerAddStoryIndex].StoryID);
//            //    }
//            //    timerAddStoryIndex++;
//            //}
//            //else//no more stories
//            //{
//            //    markerRedrawTimer.Stop();
//            //    markerRedrawTimer.Tick -= new EventHandler(addMarkerTimer_Tick);
//            //    timerAddStoryIndex = 0;
//            //    timerAddStories = null;
//            //}

//        }
//    }
//}

/// <summary>
/// This method fetches from the database the objects specified by the caller (timeslots, categories, stories)
/// and adds all the data into a single string.
/// The caller methods 'initialiseCategories()', 'initialiseTimeSlots()', or 'addDownloadedMarkersToMap()' split
/// this string into pieces, making the data more accessible.
/// The split string array is then processed by the application as necessary.
/// </summary>
/// <returns>a string which contains all the respective objects from the database</returns>
//private string downloadRequestFromDB(string downloadRequestName)
//{
//    try
//    {
//        WebRequest request = WebRequest.Create(RequestPageURL);
//        request.Method = "POST";
//        string postData = downloadRequestName;
//        byte[] byteArray = Encoding.UTF8.GetBytes(postData);
//        request.ContentType = "application/x-www-form-urlencoded";
//        request.ContentLength = byteArray.Length;
//        Stream dataStream = request.GetRequestStream();
//        dataStream.Write(byteArray, 0, byteArray.Length);
//        dataStream.Close();
//        WebResponse response = request.GetResponse();
//        dataStream = response.GetResponseStream();
//        StreamReader reader = new StreamReader(dataStream);
//        string responseFromServer = reader.ReadToEnd();

//        reader.Close();
//        dataStream.Close();
//        response.Close();

//        //incase request name problem
//        if (responseFromServer.Equals("undefined request!"))
//        {
//            return "0001234";
//        }
//        else
//        {
//            return responseFromServer;
//        }
//    }
//    catch (Exception e)
//    {
//        Console.WriteLine(e.Message);
//        return "0001234";
//    }
//}

///// <summary>
///// Filters a list of stories by timeslot and category
///// </summary>
///// <param name="listToBeFiltered">the arraylist of stories that are to be filtered</param>
///// <returns>filteredStoriesArrayList -- the list of filtered stories</returns>
//private ArrayList filterStories(ArrayList listToBeFiltered)
//{
//    ArrayList filteredStoriesArrayList = new ArrayList(); //downloaded stories

//    //add valid stories to list
//    foreach (Story story in listToBeFiltered)
//    {
//        foreach (Category category in categoriesArrayList)
//        {
//            if (category.ShowFilter && category.CategoryID == story.CategoryID)
//            {
//                foreach (TimeSlot timeslot in timeSlotArrayList)
//                {
//                    if (timeslot.ShowFilter && timeslot.TimeSlotID == story.TimeSlotID)
//                    {
//                        filteredStoriesArrayList.Add(story);
//                        break;
//                    }
//                }

//            }
//        }
//    }

//    return filteredStoriesArrayList;
//}

///// <summary> 
///// Takes an arraylist of items, and randomly chooses a specified number to add
///// to the specified object array
///// </summary>
///// <param name="listToSelectFrom">The arraylist of items to choose from</param>
///// <param name="listToAddTo">The array of object to add the selected items to</param>
///// <param name="numberToSelect">The number of items to select</param>
//private void selectRandomItems(ArrayList listToSelectFrom, object[] listToAddTo, int numberToSelect)
//{
//    //to choose a certain number of any of these stories
//    ArrayList testList = (ArrayList)listToSelectFrom.Clone();
//    Random random = new Random();
//    int totalNumber = listToSelectFrom.Count;
//    int count = 0;
//    int index = 0;
//    int numOfNullIndices = 0;

//    for (int i = 0; i < listToAddTo.Length; i++)
//    {
//        if (listToAddTo[i] != null)
//        {
//            index++;
//        }
//        else
//        {
//            numOfNullIndices++;
//        }
//    }

//    if (numberToSelect > totalNumber)
//    {
//        numberToSelect = totalNumber;
//    }

//    if (numberToSelect > numOfNullIndices)
//    {
//        numberToSelect = numOfNullIndices;
//    }

//    while (totalNumber > 0 && numberToSelect > 0)
//    {
//        double rndm = random.NextDouble();
//        if (rndm <= ((double)numberToSelect / (double)totalNumber)) //true then select
//        {
//            listToAddTo[index] = (object)testList[count];
//            testList.RemoveAt(count);
//            totalNumber--;
//            numberToSelect--;
//            index++;
//        }

//        count++;
//        if (count >= totalNumber)
//        {
//            count = 0;
//        }
//    }
//}

///// <summary>
///// uses the "downloadRequestFromDB()" method to provide a string containing all the categories
///// This string is processed by this method to produce an arraylist of categories
///// </summary>
///// <returns></returns>
//private bool initialiseCategories()
//{
//    string downloadedCategories = downloadRequestFromDB(LOADCATEGORYREQUEST);
//    bool returnVal = false;
//    if (downloadedCategories.Equals("0001234")) //means an exception occurred when downloading categories
//    {
//        //TODO : do something here in case server not available...
//        returnVal = false;
//    }
//    else
//    {
//        if (downloadedCategories.Equals(""))
//        {
//            //TODO : do something here in case empty string returned (no cats in db)
//            returnVal = false;
//        }
//        else
//        {
//            string[] categoriesArray = downloadedCategories.Split(stringSplitChar);
//            int i = 0;
//            bool adminCtg;
//            while (i < categoriesArray.Length - 1)
//            {
//                adminCtg = false;
//                if (categoriesArray[i + 3].ToString().Equals("1") || categoriesArray[i + 3].ToLower().Equals("true")) { adminCtg = true; }
//                categoriesArrayList.Add(new Category(Convert.ToInt32(categoriesArray[i]), categoriesArray[i + 1].ToString(), categoriesArray[i + 2].ToString(), adminCtg, categoriesArray[i + 4].ToString(),
//                    categoriesArray[i + 5].ToString(), categoriesArray[i + 6].ToString()));
//                i += 7;
//            }
//            returnVal = true;
//        }
//    }
//    return returnVal;
//}

///// <summary>
///// uses the "downloadRequestFromDB()" method to provide a string containing all the timeslots
///// This string is processed by this method to produce an arraylist of timeslots
///// </summary>
///// <returns></returns>
//private bool initialiseTimeSlots()
//{
//    string downloadedTimeSlots = downloadRequestFromDB(LOADTIMESLOTSREQUEST);
//    bool returnVal = false;
//    if (downloadedTimeSlots.Equals("0001234")) //means an exception occurred when downloading categories
//    {
//        //TODO : do something here in case server not available...
//        returnVal = false;
//    }
//    else
//    {
//        if (downloadedTimeSlots.Equals(""))
//        {
//            returnVal = false;
//        }
//        else
//        {
//            string[] timeSlotsArray = downloadedTimeSlots.Split(stringSplitChar);
//            int i = 0;
//            while (i < timeSlotsArray.Length - 1)
//            {
//                timeSlotArrayList.Add(new TimeSlot(Convert.ToInt32(timeSlotsArray[i]), timeSlotsArray[i + 1].ToString(), timeSlotsArray[i + 2].ToString()));
//                i += 3;
//            }

//            returnVal = true;
//        }
//    }
//    return returnVal;
//}

///// <summary>
///// takes the result (string array) from downloadRequestFromDB() method, 
///// splits them and creates a story object array out of it.
///// This array is used to manipulate which stories should be displayed.
///// This method also calls the addMarkerToMap() method which draws the stories
///// to the map
///// </summary>
//private void fetchMuseumStories()
//{
//    string downloadedStories = "";

//    downloadedStories = downloadRequestFromDB(LOADMUSEUMSTORYREQUEST);
//    //MessageBox.Show(downloadedStories);

//    if (downloadedStories.Equals("0001234")) //means an exception occurred when downloading stories
//    {

//    }
//    else
//    {
//        if (downloadedStories.Equals(""))
//        {

//        }
//        else
//        {
//            string[] museumStoriesArray = downloadedStories.Split(stringSplitChar);
//            int i = 0;
//            while (i < museumStoriesArray.Length - 1)
//            {
//                museumStoriesArrayList.Add(new Story(Convert.ToInt32(museumStoriesArray[i]), Convert.ToInt32(museumStoriesArray[i + 1]),
//                    Convert.ToInt32(museumStoriesArray[i + 2]), Convert.ToDouble(museumStoriesArray[i + 3]),
//                    Convert.ToDouble(museumStoriesArray[i + 4]), museumStoriesArray[i + 5]));
//                i += 6;
//            }
//        }
//    }
//}
////// <summary>
////// Load up some phony stories
////// Originally this methods purpose was for demonstration use when app was not connecting to db.
////// Now, this method is here to load a some stories in case that the connection to database fails.. or any other error
////// </summary>
//////private void loadUpPhonyStories()
//////{
//////    Console.WriteLine("TODO : this method (loadUpPhonyStories - (offline management) needs to be revised?!");
//////    PointLatLng storyPosition;
//////    //story 1
//////    storyPosition = new PointLatLng(-36.881380148988356, 174.7067890442047);
//////    string storyText = "Auckland Museum visited Unitec Design & Computer Science Groups \nand were amazed by their progress on the Ahi Kaa Mapping Project.";
//////    addMarkerToMap(storyPosition, storyText, HOUSEID);

//////    //story 2
//////    storyPosition = new PointLatLng(-36.854917942560306, 174.7628042972717);
//////    storyText = "We brought our wedding and engagement rings here they had \na better selection than around home. We have been married for 25 years.";
//////    addMarkerToMap(storyPosition, storyText, RESTAURANTID);

//////    //story 3
//////    storyPosition = new PointLatLng(-36.830722284660744, 174.7456381595764);
//////    storyText = "The first time we drove over Harbour Bridge. It was so exciting \nand there was a toll.";
//////    addMarkerToMap(storyPosition, storyText, ROMANCEID);

//////    //story 4
//////    storyPosition = new PointLatLng(-36.8528747443828, 174.76333001023863);
//////    storyText = "I remember watching Uncle Tom's children's choir singing in \nAuckland Town Hall. I cried through some of the songs.";
//////    addMarkerToMap(storyPosition, storyText, ROMANCEID);
//////}
/*
void checkIfMarkerHidesOtherMarkers()
{
    int aIndex = 0;
    int bIndex = 0;
    double aHeight = 0;
    double aWidth = 0;
    foreach (GMapMarker a in MainMap.Markers)
    {
        //check to make sure it is an actual storyMapMarker and not one of many other objects used for mapMarking
        if (a.Shape.ToString().Equals("InteractiveMapApp.CustomMarkers.CustomMarker"))
        {
            a.Shape.Opacity = 0.9;
            aHeight = a.Shape.RenderSize.Height;
            aWidth = a.Shape.RenderSize.Width;
            foreach (GMapMarker b in MainMap.Markers)
            {
                if (b.Shape.ToString().Equals("InteractiveMapApp.CustomMarkers.CustomMarker"))
                {
                    //check to see in case this marker has actually already been compared to the others
                    if (b.Shape.Opacity == 1)
                    {
                        //check for 'collision'
                        if ((b.LocalPositionX > a.LocalPositionX && b.LocalPositionX < (a.LocalPositionX + aWidth)))// || (b.LocalPositionY > a.LocalPositionY && b.LocalPositionY < (a.LocalPositionY + aHeight)))
                        {
                            Console.WriteLine("there was a collision!");
                            Console.WriteLine("index a, b" + aIndex.ToString() + "," + bIndex.ToString() + " b x, y" + b.LocalPositionX.ToString() + " , " + b.LocalPositionY.ToString() + "a x, y" + a.LocalPositionX.ToString() + " , " + a.LocalPositionY.ToString());
                        }
                    }
                }
                bIndex++;
            }
        }
        aIndex++;
        bIndex = 0;
    }
        

    //at the end, clean up -> set all shapes opacity to 1 again for next time zoom happens
    foreach (GMapMarker a in MainMap.Markers)
    {
        a.Shape.Opacity = 1;
    }
}

void handleCollidingMarkers()
{
    //Markers.Shape.ClipToBounds()?
}
 */
#endregion